Error codes
Errors are returned with a code and a hint that explains how to resolve them. You can pass them directly to an AI agent for resolution. When a workspace-named code replaces an older tenant-named code, error.aliases contains the old code for compatibility; no removal date is set. This page groups a human-readable list by where each error occurs.
Pre-deploy checks (CLI)
Section titled “Pre-deploy checks (CLI)”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.
| Code | Cause | Resolution |
|---|---|---|
missing_dependency_manifest | No dependency manifest for the selected runtime | For 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_dependencies | command contains pip install / npm install / go build | Remove it and leave only the start command |
runtime_command_mismatch | The languages of runtime and command do not match (for example, node with python-slim) | Correct either one |
assets_dir_empty | assets.dir is missing or empty, or the path uses the wrong letter case | Run the build and check the path |
assets_fallback_missing | The assets.fallback file is not in assets.dir | Check the build output |
db_wiring_fail (warning) | db.mode does not match the database connection in the code | Switch to a libSQL client that reads KEELSON_DB_URL |
file_wiring_fail (warning) | State files or uploads are written to local disk | Replace this with the Files / Media SDK |
keelson.yaml validation
Section titled “keelson.yaml validation”| Code | Cause | Resolution |
|---|---|---|
invalid_keelson_config | Invalid 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 error | Correct the issue described in message |
config_missing_field | A required field such as slug, runtime, or db is missing | Add it |
env_value_not_string | An env value or key is not quoted, a key is duplicated, or a merge key is used | Quote every value and key |
description_too_long | description is longer than 300 characters | Shorten it |
workers_not_supported | workers: is present | Remove it and use crons |
DB_DATABASES_REMOVED | databases: is present | Remove it. Use db.mode: libsql for persistent data |
SQLITE_LOCAL_SQLITE_INVALID_PATH | A db.local_sqlite.paths value is outside /tmp/ | Use /tmp/ or :memory: |
CRON_TIMEOUT_EXCEEDS_STANDARD_LIMIT | A crons[].timeout value exceeds 600 seconds | Reduce it or split the operation |
plan_cron_limit / plan_cron_min_interval / plan_schedule_timeout | The number, interval, or timeout of crons exceeds the plan limit | Reduce it or upgrade the plan |
reserved_path_conflict | The build output has an __keelson directory at its root | Rename the directory |
ARTIFACT_SQLITE_FILE_DRIVER | A file-based SQLite client such as sqlite3 or better-sqlite3 was detected | Migrate to a libSQL client. For temporary use, declare it in db.local_sqlite |
ARTIFACT_EXEC_NODE_CRON / _APSCHEDULER / _BACKGROUND_TASKS / _SET_INTERVAL (notice) | An in-app scheduler was detected | Move it to crons |
Deploy failures
Section titled “Deploy failures”These are shown by keelson status / keelson diagnose.
| Code | Cause | Resolution |
|---|---|---|
deploy.config.invalid | Invalid keelson.yaml content | Correct the reported key and deploy again |
deploy.config.secret_missing | A secret declared in secrets.required is not set | Set every secret with keelson secrets set <KEY> (the value is read from standard input), then deploy again |
deploy.artifact.invalid | Archive problem such as a missing lockfile or detection of a blocked item | Correct the reported issue |
deploy.build.failed | Build failed because dependency resolution failed, a build script produced an error, or the build exceeded 900 seconds | Check the deploy logs |
deploy.build.image_too_large | The image is too large | Remove unnecessary dependencies or files |
deploy.runtime.start_failed | The app exited during startup or the container did not reach the running state | Read the stored startup logs with keelson logs deploy <deploy_id>, then verify PORT and 0.0.0.0 |
deploy.runtime.health_check_failed | The app may have exited during startup, or / (or health.path) returns 5xx or does not respond within 120 seconds | Read the stored startup logs with keelson logs deploy <deploy_id>, then check the listening port and health.path |
deploy.runtime.migration_failed | db.migrate exited with a nonzero status. The previous revision continues serving traffic | Correct the migration and deploy again |
deploy.verify.failed | A verify path cannot be fetched, or the Content-Type of JavaScript or CSS does not match | Check the path and build output |
deploy.plan.limit_exceeded | A plan limit was exceeded | Reduce usage or upgrade the plan |
deploy.plan.cron_count_exceeded | The app declares more crons than the plan allows | Reduce the number of crons or upgrade the plan |
deploy.plan.cron_interval_too_short | A cron fires more often than the plan’s minimum interval | Increase the interval or upgrade the plan |
deploy.plan.schedule_timeout_exceeded | An explicit crons[].timeout exceeds the plan’s ceiling | Lower the timeout or upgrade the plan |
deploy.app.suspended | The app is suspended | Resume it before deploying |
deploy.app.operation_in_progress | The deploy could not start because another operation was in progress for this app | Wait for the other operation to finish, then deploy again |
deploy.platform.temporarily_unavailable | Temporary outage | Wait briefly and retry |
deploy.platform.error | Platform error | Contact support with the deploy_id |
deploy_in_progress (409) | Another deploy or app operation is in progress | Wait 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 exceeded | The 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 schema | Correct it and perform a normal deploy |
region_not_available (422) | The selected region is not accepting new applications | Create the app in Japan (jp-tokyo) or wait for the region to open |
region_unknown (422) | The selected value is not a Keelson logical region key | Use jp-tokyo (Japan) or us-oregon (US West), not a cloud-provider region name |
region_immutable (422) | A deploy tried to change an existing application’s placement region | Remove --region and deploy again, or create a separate application |
CLI errors
Section titled “CLI errors”| Code | Meaning | Resolution |
|---|---|---|
not_logged_in | Not logged in | Run keelson login |
multiple_workspaces / workspace_ambiguous / workspace_not_found / no_workspaces | The workspace cannot be identified | Use --workspace <slug>. Search with keelson workspaces list --query |
app_not_found | The app was not found | Check the slug. For a new app, use --new |
app_manage_required | The app exists, but you do not have manage permission | Ask 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_deleting | The app is being deleted | Wait for completion |
forbidden | You do not have permission. CONSOLE_ONLY_OPERATION identifies an operation limited to the console | Check the role and app permissions |
confirmation_required | The operation requires browser approval | Open the displayed URL and approve it. Do not run the command again |
confirmation_expired / confirmation_rejected | Approval expired after 15 minutes or was rejected | Run the command again |
deploy_failed | Deploy failed | Run keelson diagnose <deploy_id> |
sql_failed | SQL in db apply failed and was rolled back | Correct the SQL |
last_manage_binding_removed / no_effective_manager / self_lockout | access set would leave the manage group list empty or leave no effective manager | Retain a manage group. To remove yourself, use --allow-self-lockout |
transient | Temporary network error | Retry with --retry |
skill_outdated (meta.skill_outdated) | The Skill is older than the CLI | Run keelson install-agent --yes |
What users see in a browser
Section titled “What users see in a browser”| Display | State | Resolution |
|---|---|---|
| Login screen | Not logged in | Log in with an account registered in the workspace |
| ”Access denied” (403) | The user is not a member, is blocked, or lacks app view permission | Ask an administrator to register the member or grant permission |
| ”This application is only available from approved networks” (403) | Rejected by IP controls. The page shows the source IP | Ask an administrator to add an access source for that IP |
| ”The app cannot start right now because no app slot is available.” (503) | Limit on the number of apps that can run concurrently | Wait about 5 minutes. Consider priority startup or a plan change |
| ”Starting the app” | Starting from sleep | Wait a few seconds; the page reloads automatically |
| ”This application has been suspended” (503) | The app is suspended | An administrator must resume it |
| ”App not found” (404) | The URL is wrong or the app was deleted | Check the URL |
| 410 Gone | The app URL changed. The old URL is reserved for 30 days | Direct users to the new URL |
| 504 | The app did not respond within 120 seconds | Shorten the operation or move it to a cron |
| 501 | WebSocket is not supported | Use SSE or polling |
When the same situation occurs through an API or XHR request, the response has the same status as JSON and the x-keelson-error header contains the reason, such as ip-restricted, app-view-denied, capacity-full, or app-suspended.
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.
machine-forbidden and webhook-forbidden intentionally group a missing app, a token belonging to another app, and a route that disappeared so callers cannot use the response to determine whether an app exists.
X-Keelson-Auth-Error | Cause |
|---|---|
invalid-app-token | The token is invalid or revoked |
machine-scope-denied | The token scope (api / webhook) does not match the path |
machine-endpoint-denied | The path or method is not declared in auth.endpoints |
machine-forbidden / webhook-forbidden | The app is missing, the token belongs to another app, or the route disappeared |
machine-ip-not-allowed | The request came from outside the app token’s allowed IP ranges |
invalid-webhook-secret | The Webhook secret does not match |
webhook-scope-denied | The token does not have the webhook scope |
webhook-ip-not-allowed | The request came from outside the Webhook token’s allowed IP ranges |
webhook-endpoint-blocked | The path is reserved by the platform, such as /api/webhooks/email |