Skip to content

Error codes

Contract

Source: packages/shared/errors · doc/architecture/Error_Code_Catalog.md

Every REST error must use a code from this catalog. New codes go in Error_Code_Catalog.md first, then in code.

The error envelope:

{ "code": "<catalog_code>", "message": "human text", "correlation_id": "uuid", "details": {} }

correlation_id is required. details is required for validation_error.

Catalog

Auth

Code HTTP Meaning
token_missing 401 No Authorization: Bearer header
token_invalid 401 Bearer present but invalid signature, format, or issuer
token_expired 401 JWT exp in the past
token_scope_invalid 401 Token does not carry required scope/role

Authorization

Code HTTP Meaning
insufficient_permissions 403 Authenticated but not authorized for this action
admin_required 403 Admin-only route accessed by non-admin
ownership_required 403 Resource not owned by requesting user/project

Validation

Code HTTP Meaning
validation_error 400 Field-level validation failure; details required
invalid_request 400 Request shape is unparseable

Allocation

Code HTTP Meaning
allocation_not_found 404 No matching allocation
allocation_not_active 409 Action requires active allocation
allocation_already_releasing 409 Already in releasing state
allocation_concurrency_limit 409 Per-user concurrent limit hit
insufficient_balance 402 Balance below required threshold
sku_unavailable 409 No capacity matches the request

Node

Code HTTP Meaning
node_not_found 404
node_offline 409 Node not active
node_in_use 409 Node has active allocation
node_already_exists 409 Conflict on create

User

Code HTTP Meaning
user_not_found 404
user_already_exists 409

Billing & payments

Code HTTP Meaning
stripe_signature_invalid 400 Webhook signature failed verification
refund_window_exceeded 409 Outside refund_window_days; route to internal credit

Storage

Code HTTP Meaning
storage_object_not_found 404
storage_path_traversal 400 Path escape attempt rejected
storage_already_exists 409
storage_quota_exceeded 413

Catalog

Code HTTP Meaning
sku_not_found 404

Rate limit

Code HTTP Meaning
rate_limit_exceeded 429 Includes Retry-After

Server

Code HTTP Meaning
internal_error 500 Local defect — fix in owning layer
upstream_error 502/504 Upstream dependency failure
service_unavailable 503 Upstream temporarily unavailable

5xx classification rule

Per Coding_Standards.md §14:

Every new/changed 5xx response path must be classified in review as one of: - upstream dependency failure (upstream_error / service_unavailable), or - local contract/schema/query/runtime bug (internal_error).

Do not re-label local defects as upstream issues. Fix the owning layer and add a regression test.

CI gate

scripts/ci/canonical_error_guard.sh scans for error returns that don't reference the catalog and blocks the PR.

How to add a new code

  1. Open a PR that adds the row to doc/architecture/Error_Code_Catalog.md (the prose authority).
  2. Add the constant to packages/shared/errors.
  3. Reference it in OpenAPI response schemas (ErrorResponse enum).
  4. Use it in handlers/services.

The order matters: doc → constant → contract → code.

Where to look next