Sign up

Errors

Every code the API sends, whether sending the same request again can succeed, and what to do instead. Agents: branch on code and retryable, never on the sentence.

The error envelope

{"error": "<message>", "code": "<CODE>", "retryable": false, "docs_url": "https://innstance.impossibuild.ai/docs/errors#<CODE>"}
  • error is the human sentence. Print it as-is; clients that read only this field keep working.
  • code is stable once sent: branch on it, never on the sentence. A refusal with no code of its own carries the generic code for its HTTP status.
  • retryable is true when the same request, sent again after a pause, can succeed with nothing changed. Honour Retry-After when it is set.
  • docs_url links to the code on this page.

Some codes add fields of their own (upgrade, retry_after, over_pool_until, moderation). Codes are case-sensitive; a few early subscription codes are lower case and stay that way. A body over a route's size cap is refused with a plain-text 413 before any handler runs.

Machine-readable: /docs/errors.json · /docs/errors.md · /openapi.json

Error codes

CodeHTTPRetryableMeaningWhat to do
INVALID_REQUEST (generic)400noThe request is malformed or a value is not allowed.Read the message: it names the field and the rule. Fix the request and send it again.
UNAUTHENTICATED (generic)401noNo credential, or the token is unknown, revoked or expired.Sign in again (innstance login) or send a valid token as Authorization: Bearer <token>.
PAYMENT_REQUIRED (generic)402noThe request needs payment or more balance first.Pay or top up as the body describes (x402 challenges carry an accepts list), then send the request again.
FORBIDDEN (generic)403noThis account may not do this.Do not retry. The message says why; a cookie request from another origin is refused here too.
NOT_FOUND (generic)404noNo such resource on this account (another account's resources also answer 404).Check the name; list what exists (GET /apps, /sites, /agents/hosts).
REQUEST_TIMEOUT (generic)408yesThe request was cancelled before the operation finished.Read the resource's state, then send the request again if it did not take effect.
CONFLICT (generic)409noThe request conflicts with the resource's current state: a name already taken, a limit on tokens, a resource in the wrong state.Change the request or the resource as the message says; waiting alone does not clear it. A conflict that does clear by itself, after which the same request passes, has its own retryable code (OPERATION_IN_PROGRESS, POOL_LOCKED, DEPLOY_IN_PROGRESS, APP_OPERATION_IN_PROGRESS). When the work asked for is already under way (an assistant being set up), watch the resource instead of sending the request again.
GONE (generic)410noWhat the request refers to existed but has expired or been used.Start the flow again to get a fresh link, token or session.
PAYLOAD_TOO_LARGE (generic)413noThe request body is larger than this route accepts.Send less. JSON routes take up to 64 KiB; upload routes state their plan's limit in the message.
UNPROCESSABLE (generic)422noThe request is well formed but its content cannot be accepted.Change the content as the message says.
RATE_LIMIT (generic)429yesToo many requests from this account or address.Wait for Retry-After seconds (also in retry_after or retry_after_seconds when present), then send the request again.
INTERNAL_ERROR (generic)500yesThe server failed while handling the request.Retry with backoff. For a write, read the resource first: part of it may have happened.
UPSTREAM_ERROR (generic)502yesA provider the platform depends on (machines, certificates, payments, DNS) failed or answered something unusable.Retry with backoff. Failures whose outcome is unknown use OUTCOME_UNKNOWN instead.
UNAVAILABLE (generic)503yesA dependency is briefly unavailable, or coordination with another request failed.Retry after a short pause. A feature this deployment does not run answers NOT_ENABLED instead.
TIMEOUT (generic)504yesThe operation ran out of time.Read the resource's state, then retry if it did not finish. Work run on a machine, which may still be running there, answers EXEC_TIMEOUT instead.
OPERATION_IN_PROGRESS409yesAnother change to the same app, site or assistant is running, or it is still starting.Wait a few seconds and send the same request again.
NOT_ENABLED503noThis deployment does not run the feature (it is switched off in its configuration). Sent by: assistants and their settings changes, backups, volumes, custom domains, legacy CLI login, card checkout, traffic top-ups, deploys without a runner image.Do not retry; use another way, or ask the operator. A few older messages call this "temporarily unavailable"; the code is what holds.
OUTCOME_UNKNOWN500, 502, 503noThe request may already have taken effect, in whole or in part, and the server cannot confirm it. Sent by: app create, commands run with exec, runner upload completion, subscription plan changes, x402 top-ups whose settlement did not answer or answered something unusable.Do not repeat it blindly: read the target's state first (the message says what to check), then decide.
ACCOUNT_SUSPENDED403noThe account is suspended for breaking the acceptable use policy. Sent by: every sign-in route.Do not retry. The body carries the reason and an appeal link when there is one.
ACCOUNT_CHANGED403noThe browser session now belongs to a different account than the page expected.Reload the page and confirm the action with the intended account.
TOKEN_REQUEST_REPLAY409noThis token request already created a token; its secret cannot be shown again. Sent by: POST /auth/token.Check GET /auth/tokens and revoke the token if its secret was not received.
RATE_LIMIT_UNAVAILABLE503yesThe rate limiter could not record the request, so an expensive route refused it.Retry after a short pause.
FREE_TIER_DISABLED403noNew free accounts are switched off on this server.Subscribe to a paid plan (upgrade names the cheapest).
FREE_TIER_FULL403noThe free plan has reached its account cap.Subscribe to a paid plan.
APP_LIMIT403noThe plan's app count is reached. Sent by: app create.Remove an app, or upgrade to the plan named in upgrade.
SITE_LIMIT403noThe plan's published-site count is reached. Sent by: site create.Remove a site (innstance sites rm), or upgrade to the plan named in upgrade.
CPU_LIMIT403noMore CPUs per machine than the plan allows. Sent by: app create and update.Ask for fewer CPUs, or upgrade.
CPU_KIND_LIMIT403noPerformance CPUs are not included in this plan. Sent by: app create and update.Use cpu_kind shared, or upgrade.
POOL_MEMORY_LIMIT403noThe change would take the account over its plan's RAM pool. Sent by: app create and update, scale, assistant launch.Free RAM (smaller machines, fewer apps or assistants), or upgrade.
POOL_VOLUME_LIMIT403noThe change would take the account over its plan's storage pool. Sent by: volume create and extend, assistant launch.Remove or shrink volumes, or upgrade.
VOLUMES_NOT_AVAILABLE403noThe plan does not include persistent volumes. Sent by: volume create.Upgrade, or keep state in a managed database.
AUTOSCALE_LIMIT403noMore machines per app than the plan allows. Sent by: app create and update, scale.Ask for fewer, or upgrade.
DOMAINS_NOT_AVAILABLE403noThe plan does not include custom domains. Sent by: domain add.Upgrade.
DOMAIN_LIMIT403noThe plan's custom-domain count is reached. Sent by: domain add.Remove a domain, or upgrade.
ALWAYS_ON_PERFORMANCE403noThe change would add always-on performance CPU, which this account's plan does not include. Sent by: deploy, apply, scale.Follow one of the fixes in the body.
ALWAYS_ON_COST_LIMIT403noThe change would take the account's always-on machines past the plan's always-on budget. Sent by: deploy, apply, scale.Follow one of the fixes in the body.
LIMITS_UNAVAILABLE403, 503yesUsage could not be measured, so a change that needs the pool check was refused.Retry in a moment.
OVER_POOL402noThe account is over its plan's pool; over_pool_until is when the grace period ends.Reduce usage or upgrade before making further changes.
POOL_LOCKED409yesAnother change to this account's pool is being written.Retry with a short jittered backoff; the CLI does this itself.
TRIAL_EXPIRED403noThe free trial for this app or site has ended. Sent by: deploy, site upload.Upgrade (url in the body) to deploy or publish again.
SETUP_LIMIT409noToo many names are held by pages or assistants that were never finished. Sent by: site create, assistant launch.Finish or remove one of them, then try again.
NAME_TAKEN409noThe name is taken on the public namespace.Pick another name.
NAME_NOT_ALLOWED400noThe name resembles a well-known brand or the platform, or promotes gambling, adult content or scams.Pick a plainly different name; the reply never says which rule matched.
agent_name_yours409noThis account already has an assistant with this name; status says what state it is in. Sent by: POST /agents.Carry on with it (send its inputs), or destroy it first.
agent_name_taken409noThe name is held by another account, or by one of this account's sites or apps. Sent by: POST /agents.Pick another name.
UNDER_REVIEW403noThe resource is held or quarantined by trust and safety.Do not retry; it cannot be changed or deleted until reviewed. moderation carries the reasons and the appeal link.
FILE_TYPE_NOT_ALLOWED422noThe free plan publishes only web file types; files lists the refused ones. Sent by: site upload.Remove those files, or upgrade. Nothing was published.
IMAGE_NOT_CHECKABLE422noAn image could not be checked (AVIF, HEIC, JPEG XL, or far larger than a page needs). Sent by: site upload.Save it as PNG, JPEG, GIF or WebP. Nothing was published.
DEPLOY_IN_PROGRESS409yesA deploy is already running on this app. Sent by: runner deploy, app delete.Wait for it to finish (GET /apps/{name}/deployments), then retry.
APP_OPERATION_IN_PROGRESS409yesAnother deploy or app-wide operation is running.Retry when it finishes.
DELETE_FAILED502yesTearing the app down at the provider failed; the app is kept as delete_failed.Call DELETE again (retry carries a hint).
EXEC_TIMEOUT504noThe command ran out of time. It may still be running on the machine, or have finished there. Sent by: POST /apps/{name}/exec, POST /agents/hosts/{name}/exec, POST /apps/{name}/pull (archiving).Do not send the same request again: it would run the work a second time and run out of time the same way. Start a long command detached (nohup <cmd> > /tmp/log 2>&1 < /dev/null &) and poll it with short commands; innstance agents ssh has no time limit. For a backup, choose a smaller directory.
EXEC_OUTPUT_TOO_LARGE502noThe command ran, but its output was larger than an exec response can carry. Sent by: POST /apps/{name}/exec.Do not run it again as is: redirect its output to a file and fetch the file (innstance machines pull).
DOMAIN_PROOF_REQUIRED428yesOwnership of the hostname is not proven yet; nothing was written. Sent by: domain add (apps and sites).Publish the TXT record in verify (and the CNAME in records), then send the same request again.
PAYMENT_NOT_CREDITED500noThe payment settled on-chain, but the account could not be credited with it. Its transaction (tx_hash) is kept for reconciliation. Sent by: x402 top-ups (GET /subscription/topup/x402, GET /billing/egress/topup/x402).Do not pay again: the same request cannot succeed, and a fresh payment would be a second one. Check GET /subscription/topup/recent (plan days) or GET /billing/usage (traffic); if the credit has not appeared, contact support with tx_hash.
PRICING_NOT_ON_SALE409noThere is no other pricing version on sale here, so the account's plan is the one on sale. Sent by: POST /billing/pricing.Nothing to do.
PRICING_SWITCH_NOT_ALLOWED409noA switch is one way: a pricing version that is no longer sold cannot be chosen again. Sent by: POST /billing/pricing.Nothing to do; the account keeps its version.
PRICING_SWITCH_DOES_NOT_FIT409noThe account does not fit the new version's plan yet; blockers lists what stands in the way. Nothing was changed. Sent by: POST /billing/pricing.Act on each blocker, check again with GET /billing/pricing, then send the switch again.
PRICING_VERSION_CHANGED409noThe account's plan changed while it was switching; nothing was written. Sent by: POST /billing/pricing.Read GET /billing/pricing again and switch only if its preview still holds.
checkout_in_progress409yesA checkout is already open for this account.Finish or abandon it, then retry.
crypto_subscription_active409noAn active crypto subscription must be cancelled before a checkout. Sent by: POST /subscription/checkout.Cancel it first.
already_on_plan409noThe account is already on the requested plan.Nothing to do.
cancel_first409noThe account has a different recurring plan. Sent by: POST /subscription/checkout.Switch with POST /subscription/change-plan, or cancel first (the paid period is kept).
card_coming_soon503noCard checkout is not available on this deployment.Pay with USDC instead (innstance billing topup).
scheduled_change_active409noA plan change is already scheduled; scheduled_tier and scheduled_change_at say which and when.Call it off (POST /subscription/change-plan/cancel) before scheduling another.
not_configured503noPlan changes need the payment gateway, which this deployment lacks. Sent by: subscription plan changes.Do not retry.
no_subscription409noThere is no active recurring subscription to change.Subscribe with POST /subscription/checkout instead.
billing_state_mismatch409noThe platform's record of the plan and the payment gateway's disagree.Do not retry; contact support to reconcile billing.
change_reconciliation_pending409yesA previous plan change is still being reconciled with the gateway.Retry once it has landed (a few minutes).
payment_declined402noThe upgrade charge was declined.Check the payment method, or cancel and subscribe to the new plan.
no_scheduled_change409noNo plan change is scheduled.Nothing to call off.
change_not_cancelable409noThe scheduled change is already being applied.Pick a plan again once it has landed.
payments_paused503yesUSDC payments are paused on this server. Nothing was charged.Retry after the time in Retry-After, or pay by card where the plan offers it.
PERFORMANCE_ADDON_LIMIT403noThis change needs more performance machines than the account's add-ons cover, one add-on per machine.Use shared CPU, or buy the add-on the message names (innstance billing addons).
unknown_addon400noThere is no add-on with that ID.Use an ID from the message, or from GET /billing/plans.
addon_not_found404noThe account holds no active add-on in that slot.List the account's add-ons (innstance billing addons).
addon_not_for_plan403noThis plan already includes performance CPU, so the add-on would add only its RAM.Do not buy it on this plan; the message says where it is sold.
addon_needs_paid_plan403noThe add-on is for paid plans.Subscribe to the plan the message names, then buy the add-on.
addon_not_on_sale503noThis add-on cannot be bought on this server yet.Do not retry. GET /billing/plans says what is on sale.
addon_does_not_renew409noThis add-on was a one-time purchase, so there is nothing to cancel.Nothing to do: it ends on the date in ends_at.
addon_slot_ambiguous409noSeveral renewing add-ons match.Send the request again naming one slot from slots.
UPLOAD_IN_PROGRESS409yesAnother request is uploading this file right now.Wait for it, then finalize.
UPLOAD_ALREADY_RECEIVED409noThis file was already uploaded to the session; each upload URL takes one upload.Finalize, or start a new session to send different bytes.
UPLOAD_INCOMPLETE409noSome of the session's files have not been uploaded.PUT the files listed in missing to their upload_url, then finalize again.

CLI exit codes

Exit statusMeaning
0Success. domains check exits 0 only when the domain is configured and the site answers.
1The command failed; the reason is printed to stderr as Error: <message>. This covers API errors (the message carries the HTTP status, e.g. API error (409): ...), invalid flags or arguments (including those machines wait-for --help lists under 2), and a --wait-for-match or machines wait-for timeout. domains check also exits 1, after printing its report, when the domain is not ready yet.
2domains check only: the check was rate-limited (HTTP 429). Run it again after the printed number of seconds.
1-255 (passed through)machines exec and agents exec exit with the remote command's own status, so if ! innstance machines exec ... works in scripts; a status outside 1-255 becomes 1. agents ssh exits with the ssh client's status: the remote command's, or 255 when ssh itself fails.
1-255 (a local program's)A command that runs a program on your computer can exit with that program's status when the program fails. Today that is git: deploy with [secrets] in its config runs git ls-files to check the config is not committed, and a git failure other than "not tracked" (for example 128, detected dubious ownership) exits with git's status. The message on stderr says which check failed.