Skip to content

Error codes

Two catalogs: CLI error codes (in the --json envelope's error.code, with a process exit code) and web API error codes (in the HTTP response's error.code, with an HTTP status). The CLI maps HTTP failures onto its own codes — the original server message is preserved in error.message.

CLI error codes

Every CLI failure is a single JSON envelope on stdout (in --json mode):

json
{ "ok": false, "operation": "deploy",
  "error": { "code": "DEPLOY_FAILED", "message": "Deployment 8a41... failed: build exited 1",
             "hint": "Run `apco logs` to inspect the build output." } }
CodeExitMeaningTypical cause
CLOUD_NOT_LOGGED_IN2No credentials availableNever ran apco login and APCO_TOKEN unset
CLOUD_UNAUTHORIZED1Server answered an authentication/authorization 401/403Key invalid/expired or a non-business access denial
CLOUD_FORBIDDEN_SCOPE1Server answered FORBIDDEN_SCOPEToken lacks the required scope/project grant or has an invalid ci:deploy shape
CLOUD_NOT_FOUND1Server answered 404, or no project resolvableWrong id/slug; auto-slug project with no .apco/state.json — pass --project
CLOUD_UNAVAILABLE1Network failure or 5xxControl plane down/unreachable; retry later
CLOUD_REQUEST_FAILED1Business error (4xx)Quota exceeded, slug conflict, rollback unavailable, declined creation, poll timeout — message carries the server detail
CLOUD_LOGIN_DENIED1Device flow deniedUser rejected the browser approval
CLOUD_LOGIN_EXPIRED1Device flow timed outVerification code expired before approval
CLOUD_LOGIN_FAILED1Device flow failedUnexpected auth-server response
CONFIG_INVALID2~/.config/apco/config.json is corruptMalformed JSON / invalid cloud key — re-run apco login
TOKEN_REF_INVALID2Stored token ref is malformedNot one of literal: / env:NAME / file:PATH / dotenv:PATH:VAR
TOKEN_MISSING2Token ref points at nothingUnset env var, unreadable/empty token file
MANIFEST_NOT_FOUND2No apco.yml at the manifest pathRun apco init
MANIFEST_INVALID2Manifest fails validationBad YAML, schema issues (listed in hint), database/release/jobs configuration on static, existing manifest on init without --force
ENV_FILE_NOT_FOUND2env push could not find the dotenv fileMissing .env — pass --file
DATABASE_NOT_READY1Selected branch missing/not ready, or db migrate/restore failedCheck apco db status --channel <channel> --json; create it with apco db branch <channel>
DEV_SYNC_UNAVAILABLE1Plan lacks dev syncapco dev --sync pre-check against GET /account/usage
DEPLOY_TRIGGER_FAILED4Upload rejected before buildPacked archive over the size limit
DEPLOY_FAILED4Build/start failedBuild error, crash on boot — inspect apco logs --json
DEPLOY_TIMEOUT4No terminal status within 15 minutesStuck build/worker — check apco status
VERIFY_FAILED5Health path never returned 200 in timeWrong health.path/port, app not listening on PORT, DNS
CLI_INVALID_USAGE2Invalid flag/argument combinationInvalid database channel, backup list --all-channels --channel ..., --follow with --json, missing migrations dir
DESTRUCTIVE_CONFIRMATION_REQUIRED6Destructive command without --yes in --json/non-TTY modeprojects delete, db disable — re-run with --yes if intended
UNEXPECTED1Unclassified failureMessage carries the cause

Exit-code summary

ExitCodes
0success
1CLOUD_* (except CLOUD_NOT_LOGGED_IN), DATABASE_NOT_READY, DEV_SYNC_UNAVAILABLE, UNEXPECTED
2CLOUD_NOT_LOGGED_IN, CLI_INVALID_USAGE, CONFIG_*, TOKEN_*, MANIFEST_*, ENV_*
4DEPLOY_TRIGGER_FAILED, DEPLOY_FAILED, DEPLOY_TIMEOUT
5VERIFY_FAILED
6DESTRUCTIVE_CONFIRMATION_REQUIRED

Exit codes 3 and 7 are retired (Coolify era) and never emitted.

How the CLI maps HTTP errors

Server responseCLI code
Network error / unreachableCLOUD_UNAVAILABLE
Server code QUOTA_EXCEEDED, ROLLBACK_UNAVAILABLE, SLUG_CONFLICT, BACKUP_IN_PROGRESS, BACKUP_NOT_READY, or any other 409CLOUD_REQUEST_FAILED (with a targeted hint; the server code stays in the message)
Server code DATABASE_NOT_READY / DATABASE_PROVISIONINGDATABASE_NOT_READY
Server code SUSPENDED / EMAIL_NOT_VERIFIED (403)CLOUD_REQUEST_FAILED with a targeted remediation hint
Server code FORBIDDEN_SCOPE (403)CLOUD_FORBIDDEN_SCOPE
401 / 403 (any other)CLOUD_UNAUTHORIZED
404CLOUD_NOT_FOUND
5xxCLOUD_UNAVAILABLE
Any other non-2xxCLOUD_REQUEST_FAILED

Web API error codes

All /api/v1 errors use the shape { "ok": false, "error": { "code", "message" } }.

Auth & access

CodeStatusMeaning / typical cause
UNAUTHORIZED401No/invalid credential, or the user is banned
FORBIDDEN_SCOPE403Scoped API key lacks the required scope, or a scoped key hit a full-access-only route
FORBIDDEN403Admin role required (/admin/*)
SESSION_REQUIRED403POST /tokens called with an API key — token creation is session-only
EMAIL_NOT_VERIFIED403Deploys require a verified email
SUSPENDED403Project is suspended — deploy/rename/start/database ops disabled; an admin must resume

Validation & quota

CodeStatusMeaning / typical cause
VALIDATION422Invalid body/schema/slug, unsupported or conflicting database channel, channel assertion mismatches backup metadata, dev deploy on static
BAD_REQUEST400Invalid body on POST /account/set-password
INVALID_INPUT400Invalid scheduled-job filters, cursor, attempt number, or enable body
INVALID_BODY400Bad body on the SQL console, admin ban/role/plan, invites, waitlist
INVALID_EMAIL422Waitlist/invite email failed validation
QUOTA_EXCEEDED403Plan limit reached: maxProjects, maxScheduledJobs; maxDatabases distinct database-enabled projects (three branches bundled); project-wide maxBackups; or fixed 20/project saved queries. Also 422 for env over maxEnvVars
RATE_LIMITED429Per-user deploy cap (maxDeploysPerHour) reached, or a screenshot refresh requested during the per-deployment cooldown
UPLOAD_TOO_LARGE413Source upload over the plan's maxUploadMb
OCI_REFERENCE_INVALID422OCI reference/registry-host syntax or public-network policy failed before queueing
PLAN_FEATURE_UNAVAILABLE403Plan lacks the feature: managed databases, dev sync, previews, custom domains, scheduled-job execution, or OCI images (maxImageMb: 0)

Resources & conflicts

CodeStatusMeaning / typical cause
NOT_FOUND404Resource not found/not owned; selected database branch or backup ID absent
SLUG_CONFLICT409Project or plan slug already taken
CONFLICT409Unique violation on project create (name/slug race), or a saved query with that name already exists for the project
ROLLBACK_UNAVAILABLE400 / 409400: source is a dev-channel deployment. 409: source not superseded, or its image/static artifact is gone
STOP_UNAVAILABLE409No running production deployment to stop
START_UNAVAILABLE409No stopped production deployment to start
SCOPE_UNAVAILABLE409Scheduled-job definition no longer points at the exact active Production/Dev/Preview/PR route scope
ARTIFACT_UNAVAILABLE409Scheduled-job definition's pinned deployment/image is no longer runnable
SCREENSHOT_UNAVAILABLE409Screenshot refresh requested for a deployment that isn't a live production/preview one
DATABASE_PROVISIONING409Database still provisioning (drop/credentials/query/rotate while provisioning)
DATABASE_NOT_READY409Database exists but is not ready (e.g. dropping, error), or credentials missing
DATABASE_ENGINE_CONFLICT409Requested engine differs from the project's immutable first-branch engine
DATABASE_ENGINE_UNAVAILABLE503MariaDB was requested while the operator rollout gate/service is disabled
DRY_RUN_UNAVAILABLE400Rollback dry run was requested for MariaDB; use a disposable branch or an explicit transaction only for statements whose semantics you control
QUERY_ERROR400SQL console / row / count routes: the tenant engine rejected the SQL and its safe driver message is returned (also a 10s query timeout on Studio operations)
TABLE_NOT_FOUND404Database Studio row/count routes: :table is not a live base table in public
COLUMN_NOT_FOUND400Database Studio row routes: an unknown column in orderBy, values, changes, or pk
NO_PRIMARY_KEY400Row PATCH/DELETE on a table with no primary key — there is nothing to match pk against
BACKUP_IN_PROGRESS409A backup is already pending/running for the project, or deleting one that isn't complete/failed yet
BACKUP_NOT_READY409Downloading a backup whose status isn't complete
RUNTIME_LOGS_UNAVAILABLE409 / 502409: no running container. 502: worker log service unreachable/errored
PASSWORD_ALREADY_SET409set-password on an account that already has a credential — use change-password

Tokens, GitHub, account

CodeStatusMeaning / typical cause
TOKEN_CREATE_FAILED400 / 500Auth layer rejected the token creation (e.g. expiry out of range) / unexpected failure
SET_PASSWORD_FAILED400 / 500Auth layer rejected the password / unexpected failure
GITHUB_NOT_CONNECTED400No GitHub account linked
GITHUB_TOKEN_INVALID400GitHub token invalid or missing scopes — re-login with GitHub

Admin

CodeStatusMeaning / typical cause
SELF_ACTION400Admin tried to delete/ban/demote their own account
UNKNOWN_PLAN422POST /admin/users/:id/plan with a slug not in the plans table
ALREADY_SUSPENDED409Suspending an already-suspended project
NOT_SUSPENDED409Resuming a project that is not suspended
PLAN_IS_DEFAULT409Deleting the default plan
PLAN_IN_USE409Deleting a plan that still has users
CLUSTER_SCHEDULER_DISABLED409Node mutation attempted while the fail-closed scheduler rollout flag is off
NODE_ACTION_UNAVAILABLE409Node state does not allow the requested lifecycle transition or required confirmation is absent

Portable deployment failures may surface safe machine codes such as NODE_CAPACITY_UNAVAILABLE, NODE_UNAVAILABLE, NODE_FENCE_REQUIRED, STALE_NODE_OBSERVATION, NODE_TASK_FAILED, ROUTE_DIVERGED, ARTIFACT_NOT_FOUND, ARTIFACT_DIGEST_MISMATCH, and ARTIFACT_REGISTRY_UNAVAILABLE. Re-read deployment/node state before retrying; never replay an indeterminate claimed scheduled job.

Internal

CodeStatusMeaning / typical cause
INTERNAL500Unexpected server failure (slug generation exhausted, credential decryption failed, query/schema execution failure)

OCI deployment state

OCI pull/start failures are recorded as safe deployment.errorCode values and surface through status/detail while the CLI reports the terminal operation as DEPLOY_FAILED. Raw registry response bodies and credentials are never copied into the code/message/log.

CodeMeaning / action
OCI_PLAN_UNAVAILABLEThe current plan has OCI disabled; change plan configuration before retrying.
OCI_REGISTRY_BLOCKEDRegistry DNS/host resolved outside the public allow policy.
OCI_CREDENTIAL_INVALIDExact-host credential could not be loaded/decrypted; rotate it.
OCI_AUTH_FAILEDRegistry rejected or required authentication; correct the exact-host pull credential.
OCI_PULL_FAILEDRegistry pull failed with a safe generic result; inspect bounded build logs.
OCI_PULL_TIMEOUTPull exceeded 15 minutes.
OCI_IMAGE_TOO_LARGETransfer or inspected image size exceeded maxImageMb.
OCI_DIGEST_MISMATCHPull/recovery did not produce the required immutable repository digest.
OCI_PLATFORM_UNSUPPORTEDImage is not Linux/current worker architecture.
OCI_ENTRYPOINT_MISSINGImage provides neither a usable entrypoint nor command.
OCI_INSPECT_FAILEDImage metadata/size could not be verified.
OCI_DEPLOY_FAILEDSafe fallback for candidate creation/activation failure.
OCI_HEALTH_CHECK_FAILEDCandidate did not pass its configured health path before timeout.

APCO Cloud — ship apps with one command.