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.