Gateway error codes and handling
This reference covers the public Gateway data plane and Run Governance, not Admin form validation. OpenAI-shaped endpoints and Run Governance expose error.code; the Anthropic facade has no error.code, so branch on HTTP status and error.type. Record the Request ID on both facades. message is a redacted human explanation, not a stable protocol field.
The same code can use different HTTP statuses at different stages; every observed status is listed. The same status does not imply the same handling.
Request, identity, and capability
Section titled “Request, identity, and capability”| code | HTTP | Meaning and handling |
|---|---|---|
invalid_api_key | 401 | Key is missing, malformed, invalid, or revoked; repair the credential and do not retry the same value |
gateway_key_scope_denied | 403 | Key lacks the required Scope; an administrator must issue a least-privilege Key |
model_not_allowed | 403 | Project is not authorized for the public alias |
source_not_allowed | 403 | Source address is outside the Project allowlist |
model_not_found | 404 | Public Route alias does not exist |
invalid_request_error | 400 | Body, field combination, or endpoint semantics are invalid; change the request before retrying |
invalid_forwarded_for | 400 | X-Forwarded-For in the trusted proxy chain cannot be parsed safely; repair proxy configuration |
request_too_large | 400, 413 | 400 can mean one multipart field is too large; 413 means the entire request exceeds the instance or Project limit |
unsupported_feature | 400, 501 | Route/Profile cannot represent the request; 501 only means deferred execution is unavailable on this instance |
streaming_unsupported | 500 | Current HTTP writer cannot stream safely; retain the Request ID and notify the administrator |
endpoint_not_implemented | 404 | Path is outside Halro’s supported surface; choose an endpoint from the compatibility reference |
method_not_allowed | 405 | Known path does not accept this HTTP method |
route_required | 400 | File creation omitted the Halro-Route header |
ambiguous_resource_route | 409 | A resource Route has no unique eligible Deployment |
token_limit_exceeded | 400 | Per-request input or output token ceiling rejected the request |
native_redaction_incompatible | 400 | Redacting the native-protocol body would change its semantics, so Halro fails closed |
streaming_redaction_incompatible | 400 | Current streaming request cannot be combined safely with configured redaction |
Idempotency and resource state
Section titled “Idempotency and resource state”| code | HTTP | Meaning and handling |
|---|---|---|
invalid_idempotency_key | 400 | Key is empty or violates format or length requirements |
idempotency_conflict | 409 | Same Key was used for a different body or attribution; do not hide the conflict with a new Key |
idempotency_in_progress | 409 | Same create operation is running or indeterminate; query a returned resource ID, otherwise retry with the same Key, body, and attribution under a bound |
resource_not_found | 404 | Resource does not exist, belongs to another Project, or was deleted |
resource_owner_unavailable | 409 | Target bound when the resource was created cannot continue the operation |
resource_store_unavailable | 503 | Local resource state cannot be read or written safely; retry under a bound and notify the administrator |
provider_cancel_unsupported | 409 | Upstream has no provable cancellation operation; do not treat the task as stopped |
response_not_found | 404 | Deferred Response is absent, belongs to another Project, or passed retention |
deferred_response_in_flight | 409 | Response is still running and this operation requires a terminal state |
deferred_response_not_cancellable | 409 | Current state cannot be cancelled |
deferred_response_route_unavailable | 409 | Original target bound to the deferred task cannot be restored |
deferred_response_unreadable | 500 | Stored deferred result cannot be read safely; stop repeating the operation and notify the administrator |
Budget, pricing, and rate limits
Section titled “Budget, pricing, and rate limits”| code | HTTP | Meaning and handling |
|---|---|---|
budget_exceeded | 403 | Project daily budget cannot reserve this request; it did not reach a Provider and blind retry is useless |
run_budget_exceeded | 403 | Run lifecycle balance is insufficient; adjust the request or close the Run |
price_unavailable | 409, 503 | 409 means the request needs a known price or candidate prices conflict; 503 means effective pricing could not be read. Never coerce either to zero cost |
token_guard_blocked | 403 | Fixed threshold or temporary block; change request/policy or wait for its TTL according to details |
rate_limit_exceeded | 429 | Source or Project RPM; honor Retry-After with bounded backoff when present |
token_rate_limit_exceeded | 429 | Project TPM is full |
concurrency_limit_exceeded | 429 | Project concurrency is full |
deployment_concurrency_limit_exceeded | 429 | Deployment concurrency is full |
provider_concurrency_limit_exceeded | 429 | Every eligible Provider target is at its concurrency ceiling |
Run Governance
Section titled “Run Governance”| code | HTTP | Meaning and handling |
|---|---|---|
invalid_run_id | 400 | X-Halro-Run-ID is malformed |
run_governance_disabled | 403 | Project has not enabled Run Governance |
run_not_found | 404 | Run is absent or belongs to another Project |
run_not_active | 409 | Run is closed or expired |
run_governance_unavailable | 503 | Governance authority cannot be verified; Halro fails closed and the administrator must recover it |
unsupported_content_type | 415 | Governance write endpoint requires application/json |
invalid_request | 400 | Governance body cannot be decoded or violates the endpoint shape |
invalid_outcome_definitions | 400 | Outcome Definition count, uniqueness, format, or enabled state is invalid |
work_unit_not_found | 404 | Work Unit or its Definition is absent or belongs to another Project |
invalid_outcome | 400 | Outcome has no matching frozen Definition or the value is invalid |
outcome_revision_conflict | 409 | supersedes_outcome_id is not the current revision; read the latest Outcome first |
outcome_write_closed | 409 | Outcome write window has closed |
governance_unavailable | 503 | Outcome governance state cannot be read or written safely; Halro fails closed |
invalid_run | 400 | Run budget or TTL exceeds Project limits |
invalid_close_reason | 400 | Close reason is outside the 1–64 character range |
governance_rate_limited | 429 | Per-Key Governance API request rate exceeded |
governance_resource_limit | 429 | Project reached its Run Governance resource count limit |
work_unit_closed | 409 | Work Unit is closed and cannot accept this write |
Content policy and Provider
Section titled “Content policy and Provider”| code | HTTP | Meaning and handling |
|---|---|---|
content_rejected | 400 | File or audio failed content policy |
sensitive_data_detected | 400, 502 | 400 is an inbound rejection; 502 means an upstream or resource result cannot be delivered safely |
sensitive_output_detected | 422 | Provider returned content but output redaction refused delivery; the call may already be billable |
policy_error | 503 | Policy state cannot be read or executed safely |
redaction_policy_error | 500 | Internal redaction failure; stop automatic retries and notify the administrator |
provider_authentication_error | 502 | Upstream rejected Halro’s Provider credential; administrator must repair the Credential |
provider_rate_limit | 429 | Upstream throttled; Retry-After exists only when the Provider supplied a parseable value |
provider_timeout | 504 | Upstream result is indeterminate and may be billable; do not treat a resend as free |
provider_error | 502 | Upstream or response conversion failed; inspect the Attempt by Request ID and preserve uncertain cost state |
provider_unavailable | 503 | No healthy eligible Deployment; use bounded backoff and inspect Route state |
Accounting, configuration, and internal state
Section titled “Accounting, configuration, and internal state”| code | HTTP | Meaning and handling |
|---|---|---|
accounting_error | 503 | Accounting operation failed and Halro refuses to call the Provider |
accounting_unavailable | 503 | Reservation or settlement cannot complete safely; stop unbounded retries and notify the administrator |
configuration_stale | 503 | Management change persisted but new configuration did not activate safely; data plane fails closed |
internal_error | 500 | Internal gateway failure; retain the Request ID for the administrator to inspect logs, state, and integrity |
Client handling order
Section titled “Client handling order”- Save Request ID, HTTP status, and the facade’s
error.codeorerror.type; never log the Key or request body. - For 400, 401, 403, and 404, normally repair the request, permission, or configuration before retrying.
- For 409, read the resource or current state first. If
idempotency_in_progressreturns no resource ID, retry with the same Key, body, and attribution under bounded backoff. Preserve the Key and escalate persistent conflicts instead of changing it. - For 429, honor
Retry-Afterwhen present; otherwise use jittered application backoff and a maximum attempt count. - A 502, 504, or disconnect can represent a Provider Attempt and cost that already happened; inspect Usage before resending.
- Accounting, governance, policy, or
configuration_stale503 means safe authority is unknown. Let the administrator recover it instead of creating a second failure with unbounded retries.
Anthropic facade error types
Section titled “Anthropic facade error types”/v1/messages and /v1/messages/count_tokens return an Anthropic-shaped envelope with top-level type, error, and request_id. error has type and message but no code. Halro maps the final HTTP status as follows:
| HTTP | error.type |
|---|---|
| 401 | authentication_error |
| 403 | permission_error |
| 404 | not_found_error |
| 413 | request_too_large |
| 429 | rate_limit_error |
| 500, 502, 504 | api_error |
| 503 | overloaded_error |
| Actual upstream 529 | overloaded_error |
| Every other status, including 400, 409, 415, 501 | invalid_request_error |
An Anthropic client therefore cannot read the preceding code table directly from the response. Map HTTP and error.type to the same retry and human-response policy.
See Authentication, request headers, and errors for the envelope, Request ID, and Scopes, and Daily operations, integrity checks, and alerts for production investigation.