Skip to content

Error codes and exit codes

This page lists every stable AWC error code, its retryability, and its HTTP status. It then lists the awcctl exit codes from spec Appendix E. The normative source is spec §13.15 and Appendix E.

Clients branch on the stable error code string, not on the human-readable message. The code string never changes form or meaning across releases (spec §13.15).

Wire error envelope

Every API error is returned as a JSON document with one error object.

{
  "error": {
    "code": "WRITER_LEASE_HELD",
    "message": "lease held by run-991",
    "request_id": "req_7",
    "retryable": true
  }
}
Field Type Present Meaning
code string Always Stable error code in SCREAMING_SNAKE_CASE. Clients branch on this (spec §13.15).
message string Always Human-readable detail. Must not contain secrets (spec §19.5).
request_id string When set Request id for tracing. Omitted when no id is in scope.
retryable boolean Always Whether a retry with backoff may succeed. See the table below.

The request id echoes the x-request-id request header. Mutations also carry an idempotency-key header (spec §13.1).

Stable API error codes

The code is authoritative for clients. The HTTP status is advisory. The retryability comes from the classification in the code.

The retryable boolean on the wire reflects the effective retryability for that error instance. A server can override the code default for one instance. Absent an override, the value is the code default listed here.

Code Retryability HTTP status Meaning
ALREADY_EXISTS permanent 409 The resource already exists and cannot be recreated.
CHECKPOINT_PUBLICATION_FAILED transient 500 Publishing a checkpoint failed.
CONTROL_PLANE_UNAVAILABLE transient 503 The control plane is unavailable.
HOST_NOT_AUTHORIZED permanent 403 The host is not authorized to act for this workspace.
IDEMPOTENCY_CONFLICT permanent 409 An idempotency key or request conflicts with a prior submission.
INVALID_ARGUMENT permanent 422 The request is malformed or semantically invalid.
LOCAL_IO_ERROR transient 500 A local I/O error occurred on the host.
MOUNT_UNSUPPORTED permanent 422 The requested mount mode is unsupported on this host.
NOT_FOUND permanent 404 The referenced resource does not exist.
OBJECT_CORRUPT permanent 422 An object failed integrity verification.
OBJECT_MISSING permanent 422 A referenced object is missing from the store.
OBJECT_STORE_UNAVAILABLE transient 503 The backing object store is unavailable.
PERMISSION_DENIED permanent 403 The caller is authenticated but not allowed.
QUIESCE_FAILED transient 409 The quiesce required for the operation failed.
RESOURCE_EXHAUSTED transient 429 A resource limit (disk, memory, rate) was exhausted.
SNAPSHOT_NOT_READY transient 409 The referenced snapshot is not yet in a usable state.
STALE_LEASE_GENERATION permanent 409 The supplied lease generation is stale.
UNAUTHENTICATED permanent 401 Authentication is missing or invalid.
WORKSPACE_BUSY transient 409 The workspace is busy and cannot accept the operation now.
WORKSPACE_EXPIRED permanent 410 The workspace TTL has expired.
WORKSPACE_VERSION_CONFLICT permanent 409 The workspace optimistic-concurrency version does not match.
WRITER_LEASE_HELD transient 409 A writer lease is already held and blocks the operation.

Spec §13.15 requires that errors distinguish retryable from permanent conditions. The spec lists the codes but does not assign the classification. The code is the authority for the retryability column.

awcctl retryable HTTP set

The awcctl client retries transient HTTP statuses before it surfaces an error. It is a client policy. The spec does not enumerate it.

HTTP status Retryable Note
408 Yes Request timeout.
425 Yes Too early.
429 Yes Rate limited. Honor Retry-After when present.
5xx except 501, 505 Yes Server-side or data-plane failure. Includes 500, 502, 503, 504.
501 No Not implemented. Permanent.
505 No Version not supported. Permanent.
All other 4xx No Caller error. Surface immediately.
All 2xx, 3xx No Not an error.

awcctl honors a server Retry-After header, clamped to the backoff cap. The default retry policy bounds retries to three attempts, with an exponential base of 200 ms, a cap of 5 s, and full jitter. The idempotency key on mutations makes a retry safe for POST requests (spec §13.1).

awcctl exit codes

Every failure path in awcctl funnels through one error type and exits with one code from spec Appendix E. The table below is the Appendix E contract.

The exit code is a coarse signal. For the exact condition, parse the JSON error document that awcctl --output json prints. That document carries the control-plane code when one is known, plus the matching exit_code.

Code Meaning Retryable
0 Success n/a
2 Invalid command or argument No
3 Authentication or authorization failure No
4 Resource not found No
5 Conflict, busy workspace, or stale version Mixed
6 Local host or mount failure Mixed
7 Object-store or remote I/O failure Mixed
8 Checkpoint or integrity failure Mixed
9 Resource limit exceeded Yes
10 Temporary control-plane unavailability Yes

The Retryable column gives the dominant case. Several exit codes aggregate both transient and permanent error codes. The authoritative retry signal is the retryable boolean in the API error envelope, not the exit code.

Error code to exit code mapping

The table below shows which stable error codes map to each non-zero exit code.

Exit code Error codes that map to it
2 INVALID_ARGUMENT, MOUNT_UNSUPPORTED
3 UNAUTHENTICATED, PERMISSION_DENIED, HOST_NOT_AUTHORIZED
4 NOT_FOUND
5 ALREADY_EXISTS, IDEMPOTENCY_CONFLICT, SNAPSHOT_NOT_READY, WORKSPACE_EXPIRED, WORKSPACE_BUSY, STALE_LEASE_GENERATION, WORKSPACE_VERSION_CONFLICT, WRITER_LEASE_HELD
6 LOCAL_IO_ERROR
7 OBJECT_MISSING, OBJECT_STORE_UNAVAILABLE
8 OBJECT_CORRUPT, CHECKPOINT_PUBLICATION_FAILED, QUIESCE_FAILED
9 RESOURCE_EXHAUSTED
10 CONTROL_PLANE_UNAVAILABLE

CLI-local failures that never carry a control-plane code also map to these exit codes: a bad identifier or a missing option exits 2; a local I/O failure or an unreachable host daemon exits 6; a transport, decode, or object-store failure exits 7; a checkpoint stream that ends without a result exits 8.

gRPC status to exit code mapping

The awcd host daemon speaks gRPC. When awcctl receives a gRPC status, it maps the tonic code to an Appendix E exit code.

gRPC code Exit code
Ok 0
InvalidArgument, AlreadyExists 2
Unauthenticated, PermissionDenied 3
NotFound 4
Aborted, FailedPrecondition, Cancelled, OutOfRange, DeadlineExceeded 5
Unimplemented, Internal, Unknown, DataLoss 6
ResourceExhausted 9
Unavailable 10

Current scope

The error model, the retryability classification, the HTTP status mapping, the JSON envelope, and all Appendix E exit codes are implemented in the current build. Of the 22 stable codes, 15 are constructed by a code path. The remaining 7 — CHECKPOINT_PUBLICATION_FAILED, HOST_NOT_AUTHORIZED, LOCAL_IO_ERROR, MOUNT_UNSUPPORTED, QUIESCE_FAILED, STALE_LEASE_GENERATION, and WORKSPACE_VERSION_CONFLICT — are declared with stable string forms, retryability, HTTP status, and exit-code mappings, but no code path constructs them yet. Their rows in the tables above describe the contract a future emit site must honor; until then a client will not see them on the wire. The HTTP status mapping is the live response status applied by the control plane, with a fallback to 500 if a future code lacks a mapping.

The retryable HTTP set and the retry policy defaults are awcctl client behavior. They are not part of the spec and are not negotiated with the server.

This page verifies the definitions and the mappings. It does not verify that every code is reachable on every endpoint.