Skip to content
pilots
Dashboard
All pages

Errors

Every failure answers in the same shape, and the useful field is the one naming what to do next. Branch on the code, never on the wording: the sentence is written for a person and it will be reworded.

{
  "error": "a sentence for a person",
  "code": "health_gate_failed",
  "next": "the one thing to do about it",
  "details": { }
}

code is a closed list. next names the command or the call to make now. details is typed per code and absent otherwise. The CLI prints the error and then next on its own line, and --json prints the server's body unchanged.

Every code

Code Status What it means
bad_request 400 The request is malformed or missing a field. The answer names which.
unauthorized 401 No key, or a key that does not resolve. Sign in, or set the key variable.
scope_required 403 The key resolves but lacks the scope. Mint one that has it.
self_only 403 A machine’s own token reached past the machine it was minted for. Act on that machine, or use an API key for anything wider.
repo_not_connected 403 This organization has no claim on the repository named. Connect it with an admin-scoped key, or send a tar of the directory instead.
not_found 404 No such object, or this key belongs to another organization.
conflict 409 An operation is already running on it. Wait for it to finish.
volume_in_use 409 A volume is attached or mounted elsewhere. The answer names what holds it.
payload_too_large 400 A field is too big to live in a replicated row. Put the value in a volume or in object storage and reference it.
quota_exceeded 429 The organization is at a ceiling. The answer names which limit.
no_capacity 507 The request was fine and the fleet has no room for the machine. Ask for a smaller one, free some, or add a host.
not_configured 400, 501, 503 This host or fleet was built without the piece. The answer names it.
not_implemented 501 The route is not built yet.
unavailable 503 The host that writes this object is unreachable. Retry in a minute.
internal 500 The host broke. Retry once, and say so if it repeats.
plan_unsupported 400 The compose file asks for something pilots does not do.
compose_invalid 400 The compose file does not parse. The message names the file.
unknown_framework 400 No compose file, no Dockerfile, no recipe.
plan_multi_service 400 A push tried to deploy a repository holding more than one app.
build_failed on the log line The build stopped. The line carrying the failure says where.
health_gate_failed 422 The replica never answered its health check.

The two that carry details worth reading

health_gate_failed carries the service, the replica, the release, the grace it was given, and the last thing the probe saw: a status and a body when the replica answered, and an error when it did not. It carries NO address, because the probe target is the host's own view of the replica and is not reachable from where you are reading the error. A refused connection there means one of two things and almost nothing else: the app is listening on the wrong port, or it bound the loopback address instead of all interfaces.

unknown_framework carries the directory, what was looked for, the listing, the manifests, any workspaces, and the rules a Dockerfile must obey. That is enough to write one without opening the repository again (deploy).

What to do

You got Do
Any error Read next and do that.
health_gate_failed Diagnose the replica named in the answer, then fix the app. Do not redeploy first.
build_failed Read the log line carrying the failure, fix it, build again.
unknown_framework Write the Dockerfile from the details, build with it, and deploy that build under a name.
internal Retry once. If it repeats, say so rather than working around it.
A 503 about a machine whose owner is gone Retry. The host that would bring it back is still joining the fleet and claims nothing until its replica has caught up. A host says so about itself on its health route, and it clears itself within seconds.

Three habits to avoid

  • Parsing the sentence. It is for a person and it will be reworded.
  • Retrying a failed health gate by deploying again. Nothing changed, so nothing will.
  • Treating a not_found as proof the object does not exist. A key scoped to another organization gets the same answer, on purpose.