Skip to content
Console →
Website →
Asking an AI? Paste this URL https://keelson.dev/llms.txt

Error codes and resolutions

This page covers common Keelson errors, where to find them, and how to resolve them. It includes CLI errors, deployment failures shown in the console, and errors when accessing deployed apps.

For CLI errors, inspect code, message, and, when present, hint. For deployment failures in the CLI or API, inspect failure_code and failure_hint. Follow any guidance returned with the error before this page: it is specific to that situation. Include these details when asking an AI agent to investigate or fix a problem.

This is not an exhaustive list. For unlisted codes, read the returned message and guidance.

The location and response format depend on where the operation runs.

LocationHow to inspect the error
ConsoleOpen the app overview or deployment history to see the failure reason and logs
CLIRead the terminal error. With --json, standard output contains error with fields such as code, message, hint, and retryable
Deployment failure (keelson status / keelson diagnose)Inspect failure_code and failure_hint
Keelson APIMessages are generally in detail; input validation can return an array. Some approval, snapshot, validation, and manage-permission errors use error with code, message, hint, and other fields
App access denied at the gatewayBrowsers receive an explanation page; fetch / XHR receives JSON such as {"detail":"ip-restricted"}. Check X-Keelson-Auth-Error for the reason
No available app slot or suspended app at the gatewayHTTP 503 with x-keelson-platform-error: capacity-full or app-suspended. Capacity errors also include X-Keelson-Error-Code: CAPACITY_FULL
Missing URL, suspended app, or reserved path at the edgeHTTP 404 / 410 / 503 / 403. Browsers receive an explanation page and API clients receive plain text; some reserved paths also return plain text to browsers. Inspect x-keelson-platform-error. These requests do not reach the gateway and have no X-Keelson-Auth-Error
Files / Media deliveryInspect x-keelson-error. Some codes also return JSON containing error, hint, and doc

Example CLI error with --json:

{
"error": {
"code": "not_logged_in",
"message": "Not logged in.",
"hint": "Run `keelson login` or set KEELSON_TOKEN, then retry the command.",
"retryable": false
}
}

retryable indicates whether retrying the same operation may succeed. HTTP status alone is insufficient: a 503 may have retryable: false, and some build-related 429 errors, such as the cumulative trial allowance, do not clear by waiting.

These findings are reported before upload and can also be checked with keelson deploy --check. Errors stop the deployment; warnings do not. A missing dependency manifest is an error for Go, but only a warning for Python and Node.js.

A dependency manifest declares the libraries an app uses, for example go.mod, requirements.txt, or package.json. Go requires go.mod even without external libraries.

CodeCauseResolution
missing_dependency_manifestNo dependency manifest for the selected runtimeFor Go, add go.mod to the project root. For Python or Node.js, add a manifest if the app uses external libraries; no dependency manifest is required for a standard-library-only app
command_installs_dependenciescommand contains pip install / npm install / go buildRemove it and leave only the start command
runtime_command_mismatchThe languages of runtime and command do not match (for example, node with python-slim)Correct either one
assets_dir_emptyassets.dir is missing or empty, or the path uses the wrong letter caseRun the build and check the path
assets_fallback_missingThe assets.fallback file is not in assets.dirCheck the build output
db_wiring_fail (warning)db.mode conflicts with database connection code; rules cover a production connection that does not read KEELSON_DB_URL, a local-development file: fallback left on the production path, and declaration mismatches. Keeping file:local.db as the fallback when the environment variable is absent is fineFollow hint. A common fix is to use a libSQL client that reads KEELSON_DB_URL
file_wiring_fail (warning)State files or uploads are written to local diskUse the Files / Media SDK
icon.pathThe icon file is missing, unreadable, a symbolic link, or excluded from the uploadPut the image inside the project where it is uploaded, and set icon relative to keelson.yaml. See icon
icon.format / icon.size / icon.dimensions / icon.corruptThe icon image is not PNG, JPEG, or WebP; is larger than 256 KB; is outside 32 to 2048 pixels on a side; or has an unreadable headerExport the image again as PNG, JPEG, or WebP within the limits

The following errors prevent deployment.

CodeCauseResolution
invalid_keelson_configInvalid YAML, a db.mode other than libsql / none, db.migrate used with none, env beginning with KEELSON_, a path under /__keelson, an unknown runtime, more than 10 crons, or another configuration errorCorrect the issue described in message
config_missing_fieldA required field such as slug, runtime, or db is missing; static sites also require type and assetsAdd the missing field
env_value_not_stringNon-string env values, ambiguous YAML keys, duplicate keys, or merge keys (<<)Quote values or use block scalars. Quote ambiguous keys such as on, yes, or numbers. Remove duplicates and expand merge keys; quoting does not make duplicates or merge keys valid
description_too_longdescription is longer than 300 charactersShorten it
workers_not_supportedworkers: is presentRemove it. Use tasks for work that runs in response to a request and crons for time-triggered work
DB_DATABASES_REMOVEDdatabases: is presentRemove it. Use db.mode: libsql for persistent data
SQLITE_LOCAL_SQLITE_INVALID_PATHA db.local_sqlite.paths value is outside /tmp/Use /tmp/ or :memory:
CRON_TIMEOUT_EXCEEDS_STANDARD_LIMITA crons[].timeout value exceeds 600 secondsReduce it to 600 seconds or less, or split the operation
plan_cron_limit / plan_cron_min_interval / plan_schedule_timeoutJob count, interval, or timeout violates plan limitsReduce the count, increase the interval, shorten the timeout, or choose a plan that supports the required settings
tasks_require_command_or_cronstasks is declared, but there is neither command nor crons, so no code can enqueue the tasksAdd the command of the web app that enqueues the tasks, or a job in crons
task_name_conflicts_with_cronA tasks[].name matches a crons[].name after removing surrounding whitespace and lowercasingRename the task or the job
TASK_TIMEOUT_EXCEEDS_STANDARD_LIMITA tasks[].timeout value exceeds 600 secondsReduce it to 600 seconds or less, or split the work into smaller tasks
plan_task_timeoutAn explicit tasks[].timeout exceeds the plan’s limit per runShorten the timeout, or choose a plan with a higher limit. An omitted timeout is reduced to the plan limit instead of being rejected
ARTIFACT_SQLITE_FILE_DRIVERA file-based SQLite client such as sqlite3 or better-sqlite3 was detectedMigrate to a libSQL client. For temporary use, declare it in db.local_sqlite

A __keelson directory at the root of the build output fails the build. The failure_code is deploy.build.failed, and the build log contains reserved_path_conflict. Rename the directory.

These are warnings and do not fail deployment by themselves. Respond according to the purpose of the code.

CodeCauseResolution
ARTIFACT_EXEC_NODE_CRON / ARTIFACT_EXEC_APSCHEDULERScheduled work is registered inside the app processIt will not run while the app sleeps. Extract a standalone command and declare it in crons in keelson.yaml
ARTIFACT_EXEC_BACKGROUND_TASKSWork runs after the response is returnedawait short external calls and work required for request success before returning the response. Declare work that continues after the response in tasks and enqueue it with the SDK (Background tasks)
ARTIFACT_EXEC_SET_INTERVALServer-side code uses setIntervalNo change is needed for work such as cache refreshes where missed runs are harmless. Move work requiring ongoing scheduled execution to crons

Check the app overview or deployment history in the console for the reason and logs. In keelson status, keelson diagnose, or the API, inspect failure_code and failure_hint. The table also includes errors that prevent deployment from being accepted.

CodeCauseResolution
deploy.config.invalidInvalid keelson.yaml contentCorrect the reported key and deploy again
deploy.config.secret_missingA secret declared in secrets.required is not setSet every secret with keelson secrets set <KEY> (the value is read from standard input), then deploy again
deploy.artifact.invalidUploaded archive failed validation, for example because a required lockfile is missingFix the files or code identified in the error
deploy.artifact.assets_invalidFiles declared by assets.dir or assets.fallback are missing from the uploadBuild locally and redeploy
deploy.build.failedDependency resolution, a build script, or a reserved-path collision caused a build failureRead the end of the build output with keelson logs deploy <deploy_id>
deploy.build.timed_outBuild exceeded its time limitRemove unnecessary dependencies or move expensive preprocessing out of the build
deploy.build.image_too_largeThe image is too largeRemove unnecessary dependencies or files
deploy.runtime.start_failedThe app exited during startup or the container did not reach the running stateRead the stored startup logs with keelson logs deploy <deploy_id>, then verify PORT and 0.0.0.0
deploy.runtime.health_check_failed/ or health.path did not return an accepted response (2xx / 3xx / 404) within the startup and health verification time limit. This includes exiting during startup or repeatedly returning 401 / 403 / 5xxRead stored startup logs with keelson logs deploy <deploy_id>; check the listening port and health.path
deploy.runtime.migration_faileddb.migrate exited nonzero; the previous revision continues servingFix the migration and redeploy. Partially applied database changes are not automatically undone
deploy.verify.failedA verify path is unreachable, or JavaScript / CSS Content-Type does not matchCheck paths and build output. Details appear as verification_* codes in failure_logs
deploy.plan.limit_exceededA plan limit was exceededIdentify the limit in failure_hint, adjust settings or usage, or choose a plan with the required limit
deploy.plan.cron_count_exceededThe app declares more crons than the plan allowsReduce the number of crons or upgrade the plan
deploy.plan.cron_interval_too_shortA cron fires more often than the plan’s minimum intervalIncrease the interval or upgrade the plan
deploy.plan.schedule_timeout_exceededAn explicit crons[].timeout exceeds the plan’s ceilingLower the timeout or upgrade the plan
deploy.app.suspendedKeelson has restricted the app or workspaceContact support. A user or administrator cannot remove this restriction by resuming the app
deploy.app.operation_in_progressThe deploy could not start because another operation was in progress for this appWait for the other operation to finish, then deploy again
deploy.platform.temporarily_unavailableTemporary outageWait and retry up to three additional times. If it still fails, contact support with deploy_id
deploy.platform.errorPlatform errorRetrying will not resolve it. Contact support with deploy_id
deploy.cancelledDeployment was cancelledRedeploy if needed
deploy_in_progress (409)Another deploy or app operation is in progressWait for the operation to finish, then run the same command again
build_rate_limit_exceeded / build_guardrail_exceeded (429)The limit for build count, build time, concurrent builds, or consecutive failures was exceededThe message states when the restriction clears. For consecutive failures, fix the cause and wait until the stated time. The trial build allowance is cumulative and does not reset by waiting; change plans in that case
saved_config_unsupported (409)The keelson.yaml for a redeploy or rollback does not conform to the current schemaCorrect it and perform a normal deploy

Inspect executions[].failure_code in keelson crons runs list --json. Use keelson logs cron to investigate execution logs too.

cron.failed.* means a job started and failed; dispatch_failed means it could not be started. cron.skipped.* means a scheduled run was skipped because its execution conditions were not met.

CodeMeaning
cron.failed.command_failedCommand exited nonzero
cron.failed.timed_outExceeded timeout
cron.failed.terminated_no_callbackExecution ended without reporting a result
dispatch_failedCould not start execution
cron.skipped.schedule_disabledJob is disabled
cron.skipped.quota_exceededPlan execution allowance exceeded
cron.skipped.due_to_lock / cron.skipped.lease_heldPrevious run has not finished
cron.skipped.missed_runSkipped because the scheduled time had passed
cron.skipped.app_suspendedApp is suspended
cron.skipped.plan_downgradeA plan change made the job ineligible to run

These errors are returned by the Tasks SDK when the app calls enqueue or get. Each SDK raises or returns one error type (Python and Node.js TasksError, Go *tasks.Error) with code, status, and message. Branch on code; do not depend on the wording of message. See Background tasks for how to use tasks.

CodeMeaningWhen it occursResolution
TASK_INVALID_REQUESTThe task name is empty, idempotency_key is not 1–128 printable ASCII characters, the payload cannot be serialized to JSON, or the request is otherwise malformedenqueue, on Keelson and locallyFix the arguments. Retrying the same call does not help
TASK_NOT_DECLAREDThe task name is not in the currently deployed tasks (locally: not in keelson.yaml), including a name removed from tasksenqueue, on Keelson and locallyDeclare the task in tasks and deploy, or correct the name
TASK_NOT_FOUNDThe task_id does not exist or belongs to another app. Locally, get knows only tasks enqueued in the same processget, on Keelson and locallyCheck the task_id your app saved
TASKS_UNAVAILABLETask intake is closed, or the app is suspended, quarantined, or being deleted. Retrying does not helpenqueue, on Keelson onlyCheck the app’s status in the console. For a restricted app, contact support
TASK_PAYLOAD_TOO_LARGEThe request body, payload and idempotency_key serialized as JSON, exceeds 65,536 bytesenqueue, on Keelson and locallyStore large input in the database or with the Files SDK and pass its ID in payload
TASK_BACKLOG_LIMIT_EXCEEDEDThe app already has 1,000 tasks waiting to start (queued)enqueue, on Keelson onlyWait until waiting tasks start, or enqueue less often. Tasks already enqueued are not affected
TASK_MONTHLY_QUOTA_EXCEEDEDThe workspace’s monthly Background Jobs allowance cannot cover the first attemptenqueue, on Keelson onlyIntake can reopen within the same month when reserved allowance is returned, on a plan upgrade, or at the start of the next UTC month. Do not assume it stays closed until next month. The SDK does not retry it automatically
TASKS_UNAVAILABLE_TRANSIENTA temporary outage: 502 / 503 / 504 without an error body, a connection failure, or the 15-second timeout per callenqueue and get, on Keelson onlyThe SDK retries up to 3 attempts in total. enqueue retries only with an idempotency_key; add one so a retry does not create a duplicate task
TASKS_UNAUTHORIZEDThe runtime API rejected the identity token (401)enqueue and get, on Keelson onlyContact support if it persists
TASKS_FORBIDDENCloud Run rejected the call (403). Right after the first deploy that declares tasks, the permission can take a few minutes to take effectenqueue and get, on Keelson onlyWait a few minutes after the first deploy with tasks, then try again. Contact support if it persists
TASKS_SERVER_ERRORAnother 5xx response without an error bodyenqueue and get, on Keelson onlyRetry later. Use an idempotency_key when retrying enqueue
TASKS_HTTP_ERRORAnother unsuccessful response without an error bodyenqueue and get, on Keelson onlyContact support if it persists
TASKS_UNEXPECTED_RESPONSEA successful response did not have the documented shapeenqueue and get, on Keelson onlyUpdate the SDK. Contact support if it persists
TASKS_IDENTITY_TOKEN_ERRORNo identity token could be obtained from the metadata serverenqueue and get, on Keelson onlyContact support if it persists
TASKS_NOT_CONFIGUREDThe SDK could not decide between Keelson and local execution, for example because KEELSON_MODE is unknown, or KEELSON_MODE=keelson is set without KEELSON_TASKS_BASE_URL or KEELSON_APP_IDenqueue and getOn Keelson, do not override KEELSON_MODE or the other KEELSON_ variables. Locally, set KEELSON_MODE=local or remove the Keelson variables. See Environment variables
TASKS_LOCAL_CLI_NOT_FOUNDkeelson is not on PATHenqueue, locally onlyInstall the CLI with https://keelson.dev/install.sh
TASKS_LOCAL_CLI_FAILEDThe CLI could not run the task, for example because it is too old to have keelson dev task run, or it was interruptedenqueue, locally onlyRun keelson upgrade. Run keelson dev task run <name> --payload '<JSON>' to see the error directly

A command that exits nonzero or times out is not an enqueue error. The task ends as failed, and get reports the reason in last_failure_code.

get returns last_failure_code for a failed task, and for a task that is waiting to be retried. The app’s Background Tasks tab in the console shows the standard error of the last attempt.

CodeMeaningAttempt countedRetried
exit_nonzeroThe command exited with a nonzero codeYesYes, while attempts remain
timed_outThe attempt exceeded timeout and Keelson stopped the commandYesYes, while attempts remain
no_completionThe attempt ended without reporting its result before the deadlineYesYes, while attempts remain
delivery_failedThe attempt could not start within one hourNoNo
manifest_unresolvableThe task waited across two or more deploys, and the declaration it was enqueued with is no longer availableNoNo
quota_exhaustedA retry, or an attempt starting in a new month, could not reserve the monthly Background Jobs allowanceNoNo

There is no manual rerun. To run the work again, enqueue it again from the app.

These errors come from keelson snapshots .... Codes starting with snapshot_export_ occur in snapshots export.

CodeMeaningResolution
snapshot_plan_not_includedPlan does not include manual snapshots (all plans currently include them, so this should not normally occur)Contact support
snapshot_no_managed_dbApp does not use Managed SQLiteDeploy with db.mode: libsql to create a DB
snapshot_db_name_invalid / snapshot_db_name_unknownInvalid or nonexistent DB nameUse a name shown in hint
snapshot_already_running / snapshot_export_already_runningPrevious operation is runningWait for it to finish, then retry
snapshot_rate_limited / snapshot_export_rate_limitedRequest count limit reachedWait until the time in hint
snapshot_export_invalid_timestampTimestamp is outside the restorable rangeChoose a timestamp within the range
snapshot_app_deleting / snapshot_export_app_deletingApp is being deleted—
snapshot_launch_failed / snapshot_export_launch_failedOperation could not startRetry; contact support if it persists
snapshot_disabled / snapshot_storage_unconfigured (also applies to corresponding snapshot_export_ codes)Feature is disabled or storage is unconfiguredContact support
snapshot_not_readyDownload is not ready (X-Keelson-Error-Code header)Wait for completion
CodeMeaningResolution
not_logged_inNot logged inRun keelson login
multiple_workspaces / workspace_ambiguous / workspace_not_foundWorkspace cannot be identifiedSupply --workspace <slug>; search with keelson workspaces list --query <text>
no_workspacesNo available workspaceCreate a workspace in the console
app_not_foundThe app was not foundCheck the slug. For a new app, use --new
app_manage_requiredThe app exists, but you do not have manage permissionAsk a current manager to add you to a group with manage permission. Workspace OWNERs and ADMINs can add themselves with keelson groups members add <group> <email>
app_deletingThe app is being deletedWait for completion
forbiddenYou do not have permission. CONSOLE_ONLY_OPERATION identifies an operation limited to the consoleCheck the role and app permissions
confirmation_expired / confirmation_rejectedApproval expired or was rejected; expiry is 15 minutes for delete / SQL / restore and 30 minutes for preview / app curlRun the command again
deploy_failedDeploy failedRun keelson diagnose <deploy_id>
sql_failedSQL in db apply failed and was rolled backCorrect the SQL
usage (access set; API 409 detail.reason is last_manage_binding_removed, no_effective_manager, or self_lockout)Change would remove all manage groups, all effective managers, or your own permissionRetain a manage group. --allow-self-lockout only permits removing yourself; it cannot override the requirement for manage groups and effective managers
transientTemporary network errorSpecify a retry count, for example --retry 3

Legacy code compatibility: Some workspace-related errors include the former tenant code in error.aliases. No removal date is set.

confirmation_required means the operation needs browser approval. Open the displayed URL and approve it.

  • Delete, SQL, and restore execute when approved; do not rerun the command.
  • For preview and app curl, rerun the same command after approval with --confirmation <id>.

meta.skill_outdated, or a skill_outdated warning from keelson doctor, means the installed Skill is older than the CLI. This warning alone does not fail the command. Update with keelson install-agent --yes.

These messages appear when opening a deployed app. They are not error screens for the console itself.

DisplayStateResolution
Login screenNot logged inLog in with an account registered in the workspace
”Access denied” (403)The user is not a member, is blocked, or lacks app view permissionAsk an administrator to register the member or grant permission
”This application is only available from approved networks” (403)IP controls denied access; the page shows the source IPAsk an administrator whether the displayed IP should be allowed
”The app cannot start right now because no app slot is available.” (503)Concurrent app limit reachedA slot generally becomes available after another app occupying one receives no access for about 5 minutes. If none becomes available, ask an administrator about stopping an app or changing plans
”Starting the app”Waking from sleepWait for the page to change automatically
”This application has been suspended” (503)Suspended by an administrator or restricted by KeelsonAsk the administrator why. Contact support if the administrator cannot resume it
”App not found” (404)No app matches the URL: incorrect URL, suspended or deleted app, or a newly created app awaiting publicationCheck the URL and app status. For a newly created app, wait briefly
”This URL is unavailable” (410)App URL changed; the old URL is reserved for 30 daysAsk the administrator for the current URL

For API or XHR requests denied by the gateway, the JSON detail and X-Keelson-Auth-Error header contain reasons such as ip-restricted or app-view-denied. Capacity and suspension errors use x-keelson-platform-error with capacity-full or app-suspended.

These errors occur during requests or connections to the app. In particular, a WebSocket 501 is not itself shown as a browser explanation page; what users see depends on the app’s error handling.

HTTP statusCauseAction for the app developer
504App did not start returning response headers within 120 seconds; this is not the total streaming duration limitReduce work before the response starts. Use crons if the work can run at a scheduled time or interval
501Keelson does not support WebSocketUse SSE or polling

External integrations (app tokens / Webhook)

Section titled “External integrations (app tokens / Webhook)”

The detailed reason is returned in X-Keelson-Auth-Error; for compatibility, the JSON detail remains machine-forbidden or webhook-forbidden for IP allowlist denials.

At the gateway, a missing app route and a token belonging to another app both produce machine-forbidden or webhook-forbidden. If the edge cannot find the URL route before the request reaches the gateway, the response is 404 instead.

X-Keelson-Auth-ErrorCause
invalid-app-tokenThe token is invalid or revoked
machine-scope-deniedToken lacks the api scope
machine-endpoint-deniedThe path or method is not declared in auth.endpoints
machine-forbidden / webhook-forbiddenGateway cannot find the app route, or the token belongs to another app
machine-ip-not-allowedThe request came from outside the app token’s allowed IP ranges
invalid-webhook-secretThe Webhook secret does not match
webhook-scope-deniedThe token does not have the webhook scope
webhook-ip-not-allowedThe request came from outside the Webhook token’s allowed IP ranges

Webhooks sent to platform-reserved paths such as /api/webhooks/email are rejected at the edge before reaching the gateway, with HTTP 403 and a plain-text body. The header is x-keelson-platform-error: auth-webhook-endpoint-blocked, not X-Keelson-Auth-Error.