Domain Errors
All server errors are represented as DomainError subclasses from @repo/error. Each has a stable code used for HTTP mapping and diagnostics. Infrastructure errors are sanitized before being surfaced to clients.
Client Errors
These represent problems the client is responsible for resolving.
NOT_FOUND → 404
A requested resource or entity does not exist.
Use for client requests referencing an unknown URI, document, or resource. Do not use for upstream "not found" conditions, translate those into a more appropriate error.
CONFLICT → 409
An operation cannot be completed due to a conflict with the current resource state.
Use for duplicate keys, simultaneous edits, or business rule collisions that the client is responsible for resolving.
FORBIDDEN → 403
The authenticated client does not have sufficient permissions to perform the requested operation.
Use for authorization failures where the client is known but not allowed. Do not use to represent failures authenticating with upstream services.
UNAUTHORIZED → 401
The request is missing valid authentication credentials, or the provided credentials are invalid or expired.
Use only when the client is unauthenticated. Do not use this for failures authenticating with an upstream dependency, translate those into MISCONFIGURED, UNAVAILABLE, INVALID_RESPONSE, or a more specific error.
RATE_LIMITED → 429
The client has exceeded its allowed request quota or cost budget.
Optionally includes a retry-after duration. For upstream rate limits, use UPSTREAM_RATE_LIMITED.
Infrastructure Errors
These represent server-side or environmental failures. Details are sanitized before being surfaced to clients. All return a generic "An unexpected error occurred" message.
UNAVAILABLE → 503
The server or a subsystem is temporarily unavailable due to overload, maintenance, or an upstream outage.
Retryable. Use when the failure is environmental and not caused by the client's request.
TIMED_OUT → 504
An operation exceeded its time budget or deadline.
Use for lengthy database operations, remote calls, or background jobs that exceed their permitted duration. Generally retryable.
UPSTREAM_RATE_LIMITED → 503
A dependency (third-party API, database) has rate-limited our server.
Unlike RATE_LIMITED, the client cannot resolve this. Treat as a retryable server error.
INVALID_RESPONSE → 502
A dependency returned a response that is invalid, malformed, or does not match the expected contract.
Use when an external system is reachable but its output cannot be processed (protocol bugs, schema mismatches, incomplete implementations).
INTERRUPTED → 500
An operation was explicitly interrupted by user or system.
Use for cancellation workflows, abort signals, or purposeful operation halts triggered by higher layers.
MISCONFIGURED → 500
The application or a component is misconfigured and cannot serve its responsibilities.
Use for missing secrets, incorrect environment values, or configuration drift. Not retryable, requires operator intervention. Receives special attention in monitoring.