Skip to main content
Version: 1.8.0

Error Handling

All errors from DVARA use a consistent JSON envelope regardless of which surface returned them. Three separate services emit errors, and the tables below are grouped by source so that every row maps to behavior that actually runs:

  • Data plane errors — the DVARA LLM Gateway on port 8080, serving /v1/* and the actuator surface. The Enterprise build also exposes /actuator/license; the Open Source distribution does not.
  • Flightdeck errors — DVARA Flightdeck on port 8090, serving the Flightdeck.
  • MCP Gateway errors — served by the gateway on port 8080 alongside /v1/* (the separate MCP process was retired in 1.7.0). Approval-gate, loop-detection, and other agentic errors share the same envelope shape as the rest of the MCP errors below.

A single error code lives in exactly one of these three tables — there's no global "500-row catalog". If you can't find a code below, it means it isn't reachable on the surface you're looking at.

Error Envelope​

{
"error": {
"message": "Human-readable description of the error",
"type": "invalid_request_error | provider_error | gateway_error",
"code": "machine-readable error code",
"param": "field name, if validation error",
"trace_id": "32-character hex trace ID"
}
}
FieldTypeDescription
messagestringHuman-readable error description
typestringError category (see table below)
codestringMachine-readable error code
paramstringField name that caused the error (validation only)
trace_idstring32-character hex trace ID for debugging

Data plane errors​

Emitted by the DVARA LLM Gateway on port 8080 for every /v1/* request.

From 1.8.5, /v1/messages and /v1/messages/count_tokens give the same status and code in Anthropic's envelope instead: {"type":"error","error":{"type":...,"message":...,"code":...},"request_id":...}. There error.type is Anthropic's type for the status, such as authentication_error for 401 or permission_error for 403. See Use the Anthropic Messages API.

StatustypecodeWhen
400invalid_request_errorvalidation_errorMissing required field on the request DTO (model, messages). Emitted by request-body validation, before the gateway's exception path.
400invalid_request_errorno_providerNo provider on the route matches the requested model, or the matching provider has no credential configured.
400invalid_request_errorno_capable_providerThe route has providers but none of them support the requested response_format.
400invalid_request_errorinvalid_requestGeneric request-shape rejection (missing response_format.type, etc.) after the body has parsed successfully.
400invalid_request_errorinvalid_jsonMalformed JSON body — parsing failed before request-DTO binding. Emitted when the JSON body is malformed or unparseable.
400invalid_request_errorunsupported_response_formatDefensive provider-level check for response_format types the provider can't handle. In normal flow, capability-aware routing intercepts these requests first and returns no_capable_provider; this code surfaces only when routing bypasses capability filtering (for example, explicit model-prefix routing).
400invalid_request_errorunsupported_capabilityThe selected provider does not support the content in the request. Raised by Cohere and Groq for image content (vision) and for tool-use / tool-result content blocks, and by Gemini, Bedrock and Ollama for an https image URL when image fetching is off. Capability-aware routing does not pre-filter vision or tool-call content, so the provider itself rejects the request.
400invalid_request_errorprompt_experiment_not_runningThe named prompt experiment is not running, has no variants, or its variant weights do not total 100. Correct the experiment before retrying.
400invalid_request_errorunsupported_api_versionFrom 1.8.5, on /v1/messages: the anthropic-version header is missing or is not 2023-06-01.
400context_window_errorcontext_window_exceededEstimated input tokens exceed the provider's context window and no workspace pruning strategy is configured. In 1.8.5 the check uses one limit per provider, not the model's own window; see the known issue.
400pii_violationpii_detectedPII detected in the request and the workspace policy is BLOCK.
403pii_violationpii_tokenize_unavailableTOKENIZE was selected but this build has no reversible token store. The provider was not called.
403pii_violationpii_redact_unavailableA legacy v1 code retained for compatibility when Enterprise tokenization cannot obtain usable key or store capacity. Only TOKENIZE reaches it in 1.8; the response includes attempted_action: "TOKENIZE".
402budget_exceededbudget_cap_hardHard budget cap reached on the workspace or the API key.
402budget_exceededper_call_cost_exceededA single request's estimated cost (max_tokens × output price) exceeded the per-call ceiling, set by dvara.llm-gateway.finops.per-call-max-cost-usd or Workspace.metadata["cost.per-call-max-usd"]. Complements the accumulated-spend cap; off by default.
403policy_violationpolicy_deniedRequest blocked by an active policy rule.
403guardrail_violationguardrail_blockedGuardrail detector flagged the request at or above the configured risk threshold and the workspace action is BLOCK.
403data_residency_errordata_residency_violationGeo-aware routing found no provider in the workspace's allowed regions.
403ip_access_errorip_access_deniedClient IP blocked by global or per-workspace CIDR rule.
403workspace_credential_requiredworkspace_credential_requiredStrict-BYOK enforcement rejected the call — the workspace has no own active provider credential. Set under dvara.credentials.require-workspace-credential=true (global) or Workspace.metadata["credentials.require-workspace-credential"] (per-workspace). Audit event: PROVIDER_CREDENTIAL_MISSING.
403workspace_suspendedworkspace_suspendedWorkspace administratively suspended — trial-cliff expiry, chronic-abuse sweep, self-delete schedule, or manual operator action. Audit event per blocked request: WORKSPACE_SUSPENDED_BLOCK. From 1.8.1 a suspension applies to the next request, and lifting one is served just as quickly; before that, either direction could take about a minute on the LLM plane.
403session_killedsession_killedFrom 1.8.5, Enterprise platform. The request's X-Session-Id names a killed session. The message is "Agent session has been killed: <id>. Start a new session." It is 403, not 429, so clients do not retry. A kill lasts 24 hours. GET /v1/models and calls with no session id are not checked. See Stop a session.
413input_size_errorinput_too_largeRequest exceeds guardrail.max-input-tokens, guardrail.max-messages-per-request, or guardrail.max-message-length.
413a2a_errora2a_message_too_largeAn outbound A2A message carries more text than a2a.limits.max-message-length (50,000 characters by default). Checked before policy and the PII scan on message:send and message:stream.
422schema_validation_errorschema_validation_failedThe response failed output-schema validation. DVARA does not retry this failure automatically.
429rate_limit_errorrate_limit_exceededPer-key request count or token budget exhausted in the current 60-second window. Emitted directly by the rate-limit filter.
429priority_throttle_errorpriority_throttledPriority admission controller rejected the request because the workspace's tier is over its concurrency threshold.
429provider_rate_limitedprovider_rate_limitedThe upstream provider credential's published rate-limit budget is exhausted; the gateway shed the request after finding no capable non-shed fallback. Carries a Retry-After header derived from the upstream signal. Requires dvara.llm-gateway.provider-rate-limit.enabled=true.
502provider_errorprovider_response_too_largeFrom 1.8.5. The provider's response passed dvara.llm-gateway.response-limits.max-body-bytes (64 MiB) or, for a stream or file download, max-stream-bytes (128 MiB). Refused before it is parsed; not retried, and not counted against the provider's circuit breaker.
502provider_errorprovider_errorUpstream provider returned a non-success status, the connection failed, or a stream ended without a finish reason, had an empty body, or carried an in-band error. Provider-specific detail is prefixed to the message.
503provider_unavailableprovider_circuit_openThe provider's circuit breaker is OPEN; no upstream call was attempted.
503provider_unavailableworkspace_credential_unavailableA workspace credential exists but cannot be decrypted or resolved, or its store cannot be read. DVARA does not fall back and emits PROVIDER_CREDENTIAL_UNAVAILABLE. Enterprise platform.
503provider_unavailablefailover_capability_mismatchPrimary provider failed and no capable fallback exists. Response also carries the X-Gateway-Failover-Blocked: capability_mismatch header.

Streaming can fail after the HTTP 200 and SSE headers have been sent. In that case the status cannot change. A final content-filter event ends delivery and the audit trail records STREAM_TOO_LARGE_TO_SCAN, STREAM_TOOL_ARGUMENTS_UNENFORCEABLE, or STREAM_INCOMPLETE_UNGROUNDED. Read STREAMING_ENFORCEMENT_SUMMARY for the separate scan_incomplete, scan_failed, and truncated facts. Do not retry blindly: reduce an over-limit response, fix malformed tool arguments, or retry a truncated upstream only when the operation is safe to repeat.

Prompt-template codes (data plane)​

Emitted when a request references a template via metadata.prompt_template_id and the resolver cannot satisfy the reference.

StatustypecodeWhen
400invalid_request_errorprompt_template_not_activeReferenced template is not in ACTIVE status.
400invalid_request_errorprompt_variable_missingRequired {{variable}} not provided in the request's variables map.

DVARA Open Source resolves active templates from gateway.yaml, but it does not run prompt experiments. If a request supplies metadata.prompt_experiment_id, the Open Source data plane returns HTTP 400 with code: unsupported_capability; it does not ignore the experiment and send the call as ordinary traffic. Prompt experiments require the Enterprise platform.

Additional guardrail error codes​

StatustypecodeWhen
403guardrail_violationhallucination_detectedThe grounding-detection layer fires with action: BLOCK — response contains ungrounded claims.
500guardrail_plugin_errorguardrail_plugin_errorAn external guardrail plugin configured with fail-mode: CLOSED failed to complete its call.

Flightdeck errors​

Emitted by the DVARA Flightdeck on port 8090. Same envelope shape as the data plane, same lowercased-code convention.

These codes moved surface, they did not go away

These codes predate the removal of the Admin API in 1.7.0 and are now raised by the Flightdeck rather than by /v1/admin/**, which returns 404. The codes and their meanings are unchanged.

Authentication and authorization​

StatustypecodeWhen
401unauthorized_errorauthentication_requiredAdmin caller missing or invalid Bearer token / PAT / JWT. Emitted on authentication failure.
403forbidden_erroraccess_deniedWorkspace-scope violation: a workspace-role caller (admin / developer / viewer) tried to read or write a resource belonging to another workspace, or a caller lacked the URL-pattern RBAC role required for the path. Emits a WORKSPACE_SCOPE_VIOLATION audit event capturing the path, method, requested workspace id, and acting principal — security teams can detect probing without grepping response logs.

Request validation and parsing​

StatustypecodeWhen
400invalid_request_errorvalidation_errorMissing required field on the admin request DTO (e.g. name, email). Emitted when request validation fails.
400invalid_request_errorinvalid_jsonMalformed JSON request body — parsing failed before DTO binding.

Not-found codes (all 404 not_found_error)​

Every admin resource that supports GET /{id} returns this shape when the ID doesn't exist or belongs to a different workspace than the caller's RBAC scope allows:

workspace_not_found · api_key_not_found · route_not_found · route_version_not_found · policy_not_found · policy_version_not_found · user_not_found · credential_not_found · pricing_not_found · budget_not_found · chargeback_not_found · report_not_found · webhook_not_found · mcp_server_not_found · schema_not_found · session_not_found · prompt_template_not_found · prompt_version_not_found · prompt_experiment_not_found · mock_scenario_not_found · golden_prompt_not_found · drift_report_not_found · eval_prompt_not_found · eval_report_not_found

Request-shape and build-availability codes​

An *_not_available code means the optional implementation is not available in this build. It does not describe the licence state. From 1.8.2 no plane needs a licence, and an expired licence refuses no traffic. The only licence-related refusal is the call limit for an install without a licence; see Licence limits.

StatustypecodeWhen
400invalid_request_errorinvalid_requestGeneric request-shape rejection.
400invalid_request_errorinvalid_policy_statusPolicy status change target is not a valid lifecycle value.
400invalid_request_errorinvalid_template_statusTemplate status change target is not a valid lifecycle value.
400invalid_request_errorinvalid_report_typeCompliance report type is not one of SOC2 / HIPAA / GDPR.
400invalid_request_errorcompliance_not_availableCompliance reporting is not available in this build. The Enterprise Development posture does not licence-gate reporting when the implementation is present.
400invalid_request_errorchargeback_not_availableChargeback reporting is not available in this build. The Enterprise Development posture does not licence-gate reporting when the implementation is present.
400invalid_request_errormcp_not_availableThe requested MCP operation is not available in this build. No licence is needed for the MCP Gateway.
400invalid_request_errorencryption_not_configuredDVARA_ENCRYPTION_MASTER_PASSWORD is not set, so credential or guardrail-plugin secrets cannot be encrypted for storage.
400invalid_request_errorprompt_experiment_not_runningExperiment is not in RUNNING status.
400invalid_request_errormock_scenario_invalid_nameScenario filename failed path-traversal validation.
400invalid_request_errormock_scenario_invalidScenario Groovy source failed compile-check.
400invalid_request_errorinvalid_output_schema_scopeRegistered output schema must declare a routeId, a modelPattern, or both — neither would never match any request.
400invalid_request_errorinvalid_policy_dslPolicy YAML DSL failed compile-check (syntax error, unknown condition, unknown action).
400invalid_request_errorinvalid_storage_modeCredential storage_mode is not one of ENCRYPTED / REFERENCE.
400invalid_request_errorcredential_api_key_missingCreating or rotating a credential in the Flightdeck with storageMode=ENCRYPTED but no api_key field in the body.
400invalid_request_errorcredential_reference_missingCreating or rotating a credential in the Flightdeck with storageMode=REFERENCE but no secret_reference field in the body.
400invalid_request_errorcredential_storage_mode_mismatchRotate request used the wrong field for the credential's current storage mode (e.g. passed api_key on a REFERENCE credential).
400invalid_request_errorcredential_not_rotatableTried to rotate a credential that isn't in ACTIVE status (e.g. already REVOKED or SUPERSEDED).
409duplicate_errormcp_server_duplicateServer ID already exists for the target workspace. From 1.8.4 the Flightdeck forms show this refusal on the form, naming the ID, and keep what you typed.
409duplicate_errora2a_agent_duplicateAgent ID already exists in the workspace, on create or on a rename. From 1.8.4 the Flightdeck refuse it on the form, naming the ID, and keep what you typed; before, the operator saw "an unexpected error occurred".
409duplicate_erroruser_duplicateUser email already exists for the target workspace.
413payload_too_largemock_scenario_too_largeScenario source exceeded the 256 KB limit.
500admin_error—Default fall-through for any unmatched gateway-thrown error.

From 1.8.4 a new A2A agent ID may not contain ::, which DVARA uses to join an agent to a skill. The Flightdeck, the Flightdeck and a GitOps import refuse it with A2A_AGENT_ID_INVALID, naming the ID; use -, _ or . instead. An agent that already has such an ID keeps it.

MCP Gateway errors​

Emitted by the MCP plane, which runs inside the gateway on port 8080 under /mcp. Almost every error — auth, policy, agentic governance, upstream failure — comes back through the same lowercase-code, type: "mcp_error" envelope. MCP_WORKSPACE_SUSPENDED is the exception and is noted in the table below; a client that keys on type will not recognise it.

{
"error": {
"message": "…",
"type": "mcp_error",
"code": "mcp_server_not_found",
"trace_id": "…"
}
}
Native MCP request body failures

From 1.8.6, native POST /mcp limits the complete request body with dvara.mcp-gateway.limits.max-request-bytes, 4 MiB by default. A larger declared or chunked body receives a bare HTTP 413 before JSON-RPC processing, so it has no DVARA error envelope or code. Authentication runs first; an invalid credential still receives 401 without its body being read. This outer limit does not cover the server-scoped MCP REST bridge.

StatuscodeWhen
400mcp_not_availableThe MCP implementation needed for this operation is not available in this build. Do not use this code to infer licence state.
400mcp_upstream_rejectedFrom 1.8.4. A native MCP server answered the call with a JSON-RPC invalid request, method not found or invalid params error, such as an unknown tool. Fix the call; a retry will fail the same way. error.upstream_error carries the server's code, message and data.
410mcp_transport_sunsetFrom 1.8.5. The MCP server uses the legacy HTTP+SSE transport and its sunset date has passed (2027-07-28 by default, set by dvara.mcp-gateway.legacy-sse-sunset). Move the server to Streamable HTTP.
413mcp_arguments_too_largeFrom 1.8.5. The tool call's arguments, as JSON, are larger than dvara.mcp-gateway.limits.max-arguments-bytes (1 MiB by default) or the workspace's own limit. Refused before the schema check, policy, the PII scan and the server.
400mcp_request_state_invalidFrom 1.8.5. The client's requestState for an input round trip is not a string or is larger than 16 KiB. The same code comes back as 502 when the server sent such a state.
400mcp_pii_detectedPII detected in the tool-call arguments or response, workspace policy is BLOCK.
401mcp_auth_requiredMissing Authorization: Bearer <key> on the MCP Gateway request.
401mcp_auth_invalidAPI key does not resolve to an active workspace.
401mcp_auth_revokedAPI key has been revoked.
403mcp_policy_deniedMCP request denied by a policy rule.
403mcp_approval_deniedA human reviewer denied the tool call from the DVARA Flightdeck approval queue.
403mcp_approval_unavailableFrom 1.8.4. The tool call needed approval, the approval store could not be reached, and the workspace's default approval action is deny. No reviewer could act. Before 1.8.4 this was a 502, which clients retry.
403MCP_WORKSPACE_SUSPENDEDThe calling workspace is suspended. Since 1.7.0 each plane checks workspace state before forwarding, so suspension stops LLM requests, MCP tool calls, and A2A hops. This one refusal does not use the envelope above — measured on 1.7.0, it returns {"error":{"message":"Workspace is suspended","code":"MCP_WORKSPACE_SUSPENDED"}}: the code is UPPERCASE, and there is no type and no trace_id. Match on the status and the code, not on type.
403mcp_session_killedThe session has been killed; later tool calls for that session are refused at once. From 1.8.5 a kill made on any plane, or by loop detection, counts, and it lasts 24 hours. A call held for approval when the kill lands is refused too.
403mcp_sampling_refusedFrom 1.8.5. The server answered with a request for the client to run a model call (sampling/createMessage). DVARA never relays it, because that model call would skip the LLM Gateway's governance.
403mcp_input_request_refusedFrom 1.8.5. The server asked for input the workspace does not allow, such as a roots request (refused by default) or an elicitation the workspace turned off.
404not_found (type not_found_error)Wrong URL under /mcp (e.g. typo, excluded actuator path, bot probe). Measured on 1.7.0 — a path no controller claims is answered with the neutral envelope, not the mcp_error one. Returned when the route or path is unknown so probes to non-existent paths don't masquerade as 500 mcp_internal_error.
404mcp_server_not_foundMCP server ID not registered for the calling workspace.
408mcp_approval_timeoutApproval gate reached its configured timeout with no human decision; workspace default action is deny.
429mcp_rate_limit_exceededPer-key rate limit exhausted.
429mcp_agent_loop_detectedThe loop detector fired (repetition threshold, cycle detection, or rate cap) on the session.
503mcp_injection_scan_failedA tool response could not be scanned and the workspace injection action is BLOCK or SANITIZE; FLAG records the failure and returns the response.
502mcp_response_too_largeFrom 1.8.5. The tool result passed dvara.mcp-gateway.response-limits.max-body-bytes (4 MiB) or, for a stream, max-stream-bytes (16 MiB), or the workspace's own limit. Refused before it is parsed and not retried.
502mcp_upstream_errorFrom 1.8.4. A native MCP server answered the call with any other JSON-RPC error. error.upstream_error carries the server's code, message and data.
502mcp_server_unavailableA native MCP server could not be reached: its address did not resolve, it refused the connection, it did not answer in time, or its session could not start. The message names which. From 1.8.4 a server that answers the call with a JSON-RPC error is no longer reported this way; see the two codes above.
502(fall-through)Any other gateway-thrown error code; the MCP Gateway lowercases it, prefixes mcp_ if needed, and returns 502 mcp_error / mcp_<code>.
503mcp_server_unavailableThe MCP server is registered but not active, for example suspended, disabled or quarantined; the message names the state.
500mcp_internal_errorAny unhandled exception — caught by the generic handler branch.

From 1.8.4 an upstream JSON-RPC error comes back as the server gave it. A call to an unknown tool on POST /mcp/{serverId}/tools/call returns:

{
"error": {
"message": "The MCP server answered with an error: Unknown tool: search_artcles",
"type": "mcp_error",
"code": "mcp_upstream_rejected",
"upstream_error": {
"code": -32602,
"message": "Unknown tool: search_artcles"
},
"trace_id": "a6783439db1f46a6bfed511a0011e955"
}
}

upstream_error.data is present when the server sent data. The pooled session to the server is kept.

The native JSON-RPC /mcp endpoint represents governance refusals with application-specific JSON-RPC codes rather than this HTTP envelope. See the native MCP refusal table.

Error Examples​

Validation Error — Missing Model​

curl -X POST http://localhost:8080/v1/chat/completions \
-H "Authorization: Bearer $DVARA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "Hi"}]}'
{
"error": {
"message": "model is required",
"type": "invalid_request_error",
"code": "validation_error",
"param": "model",
"trace_id": "a6783439db1f46a6bfed511a0011e955"
}
}

No Provider Configured​

{
"error": {
"message": "No provider configured for model: gpt-4o. Set dvara.llm-gateway.providers.<name>.api-key in application.yml or as an env var.",
"type": "invalid_request_error",
"code": "no_provider",
"trace_id": "d354d2faaa5f4e14939aa8c480fb9d90"
}
}

Unsupported Response Format​

{
"error": {
"message": "Ollama provider does not support response_format json_schema. Supported formats: [text, json_object]",
"type": "invalid_request_error",
"code": "unsupported_response_format"
}
}

Workspace Not Found​

{
"error": {
"message": "Workspace not found: t-999",
"type": "not_found_error",
"code": "workspace_not_found",
"trace_id": "e9016783ab4c5d60c3ff042e3h3h7266"
}
}

Credential Not Found​

{
"error": {
"message": "Required credential not found: provider.openai.api-key",
"type": "invalid_request_error",
"code": "credential_not_found",
"trace_id": "f1234567890abcdef1234567890abcde"
}
}

Rate Limit Exceeded​

HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-Trace-ID: a6783439db1f46a6bfed511a0011e955
{
"error": {
"message": "Rate limit exceeded",
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"trace_id": "a6783439db1f46a6bfed511a0011e955"
}
}

Provider Error​

Error messages include a human-readable hint for common HTTP status codes:

{
"error": {
"message": "Anthropic API error 401 (invalid API key — check your provider credentials)",
"type": "provider_error",
"code": "provider_error",
"trace_id": "b7894561cd2e4f38a1cc820d1f1f5044"
}
}

Hints are appended for these status codes:

StatusHint
401invalid API key — check your provider credentials
403access denied — your API key may lack required permissions
404model or endpoint not found — check the model name
429rate limited by provider — too many requests
500provider internal server error
502provider returned bad gateway
503provider is temporarily unavailable

Circuit Breaker Open​

When a provider fails repeatedly, the gateway stops sending requests to it temporarily to avoid cascading failures. The error message explains what happened and what to do:

{
"error": {
"message": "Provider anthropic is temporarily unavailable — too many recent requests failed, so new requests are paused. This usually resolves automatically after a short cooldown. If it persists, check your provider API key and account status.",
"type": "provider_unavailable",
"code": "provider_circuit_open",
"trace_id": "c8905672de3f5049b2dd931e2g2g6155"
}
}

PII Detected (Block Mode)​

{
"error": {
"message": "PII detected in request — 2 entity type(s) found. Workspace policy: BLOCK",
"type": "pii_violation",
"code": "pii_detected",
"trace_id": "g0127894ab5c6d71e4ff153f4i4i8377"
}
}

Guardrail Blocked​

{
"error": {
"message": "Request blocked: guardrail violation detected (INJECTION, JAILBREAK)",
"type": "guardrail_violation",
"code": "guardrail_blocked",
"trace_id": "h1238905bc6d7e82f5gg264g5j5j9488"
}
}

Input Too Large​

{
"error": {
"message": "Request exceeds maximum messages limit: 150 > 100",
"type": "input_size_error",
"code": "input_too_large",
"trace_id": "i2349016cd7e8f93g6hh375h6k6k0599"
}
}

Schema Validation Failed​

{
"error": {
"message": "Output schema validation failed: $.name: required property missing",
"type": "schema_validation_error",
"code": "schema_validation_failed",
"trace_id": "j3450127de8f9004h7ii486i7l7l1600"
}
}

Context Window Exceeded​

{
"error": {
"message": "Estimated token count 150000 exceeds context window 128000 (no pruning strategy configured)",
"type": "context_window_error",
"code": "context_window_exceeded",
"trace_id": "k4561238ef9g0115i8jj597j8m8m2711"
}
}

Failover Blocked​

HTTP/1.1 503 Service Unavailable
X-Gateway-Failover-Blocked: capability_mismatch
{
"error": {
"code": "failover_capability_mismatch",
"message": "Failover blocked: no fallback provider supports response_format: json_schema. Primary provider [openai] failed: upstream down"
}
}

Licence limits​

An Enterprise install without a licence may make 100,000 governed calls a month: LLM calls, MCP tool calls and A2A hops counted together. Once the month's count reaches 110,000, each plane refuses the call with 402 and its own code. On /v1/*:

HTTP/1.1 402 Payment Required
Content-Type: application/json
{
"error": {
"code": "license_token_cap_exceeded",
"type": "token_cap_exceeded",
"message": "Without a licence this install can make 100,000 calls a month, counting LLM calls, MCP tool calls and A2A hops together. This month: 110,000. Calls resume on the 1st, or when the platform owner adds a licence in Flightdeck.",
"tier": "unlicensed",
"current_usage": 110000,
"cap": 100000,
"upgrade_url": "https://dvarahq.com/pricing"
}
}

/mcp/* answers 402 with code: mcp_cap_exceeded, and /a2a/* with code: a2a_cap_exceeded and type: a2a_error, with the same message. A refused call is not counted. Calls resume on the 1st of the month, or on the next request after the platform owner adds a licence in DVARA Flightdeck. No restart is needed.

A valid licence has no call limit. From 1.8.6 it counts calls without refusing any, for the monthly usage report. An expired licence counts calls but never refuses one. Until 1.8.2, an expired licence refused /mcp/* and /a2a/* with 402 LICENSE_EXPIRED; that response no longer exists. Check where the install stands with Enterprise GET /actuator/license and DVARA_ACTUATOR_API_KEY. See Get and apply a license.

A2A Gateway errors​

Enterprise only

Not included in DVARA Open Source.

StatusCodeMeaning
400a2a_not_availableThe A2A implementation is unavailable in this build.
400a2a_pii_detectedThe configured PII action refused the message.
401a2a_auth_required, a2a_auth_invalid, a2a_auth_revokedThe plane key is missing, invalid, or revoked.
401a2a_delegated_token_requiredA delegated agent call lacks its delegated token.
402a2a_cap_exceededThe monthly call limit is used up: the install-wide limit of an install without a licence (see Licence limits), or a hosted plan's A2A band.
403a2a_policy_denied, a2a_scope_denied, a2a_workspace_suspendedPolicy, scope, or workspace posture refused the call.
403a2a_session_killedThe session is on the workspace deny list. From 1.8.5 a kill made on any plane counts and lasts 24 hours. A running stream ends with an a2a_session_killed error event, and a hop held for approval is refused.
403a2a_delegation_chain_required, a2a_delegation_chain_invalidThe delegation guard refused a hop with no chain from an agent's key, or a chain that was changed, expired, or belongs to another workspace, session or agent.
403a2a_approval_denied, a2a_approval_unavailableThe required human approval was denied or unavailable.
404a2a_agent_not_foundThe agent is absent or outside the caller's workspace.
408a2a_approval_timeoutThe approval window expired.
409a2a_delegation_cycle, a2a_delegation_depth_exceededThe delegation guard refused a hop that loops back or makes the chain too deep. Do not retry.
409a2a_delegation_hop_budget_exceededFrom 1.8.5. The session has forwarded as many hops as a2a.delegation.max-hops-per-session allows. Do not retry.
429a2a_loop_detectedLoop detection stopped the agent chain.
429a2a_session_rate_limitedFrom 1.8.5. The session passed the hop rate (60 a minute). Unlike a loop, the session is not killed.
502a2a_endpoint_not_httpsFrom 1.8.5. The agent's endpoint is not https://. DVARA does not contact the peer. Move the agent to https:// or disable it.
502a2a_response_too_largeFrom 1.8.5. The peer's answer passed a2a.response-limits.max-body-bytes (16 MiB) or, for a stream, max-stream-bytes (64 MiB). Not retried; a stream is cut and ends with an error event.
502a2a_card_unavailable, a2a_card_signature_invalidAgent Card retrieval or signature verification failed. From 1.8.4 this includes a peer's authenticated extended Agent Card that its public card declares but that could not be fetched; DVARA does not fall back to the public card.
503a2a_agent_unavailableThe registered agent cannot serve traffic.
503a2a_delegation_binding_unavailableSince 1.8.4: the gateway could not read which agent the API key acts as, in a workspace that requires a chain from agents. A retry may pass.
503a2a_delegation_settings_unavailableFrom 1.8.5. The workspace's delegation settings could not be read and this gateway has never read them. The hop is not forwarded or counted. A retry may pass.
503a2a_delegation_hop_budget_unavailableFrom 1.8.5, under the hardened preset only. The session's hop count could not be read in time. A retry may pass.
503a2a_push_not_availableFrom 1.8.5. A push config was sent, but the gateway has no A2A_PUSH_CALLBACK_BASE_URL, and the workspace has not chosen direct delivery.

From 1.8.5 a peer that posts a push notification to the gateway gets 413 when the notification is larger than a2a.push.max-body-bytes, and 502 when the gateway could not deliver it to the workspace's webhook. The peer can send it again.

An unmapped A2A code returns HTTP 502. DVARA preserves an existing a2a_ prefix or adds it before returning the lowercased code.

Additional canonical codes​

StatusCodeDistributionMeaning
400invalid_pathBothThe data-plane path is not valid.
401api_key_required, invalid_api_key, api_key_revoked, api_key_expiredBothThe data-plane credential is missing or unusable.
402license_token_cap_exceededEnterpriseThe monthly call limit is used up on /v1/*. See Licence limits.
402mcp_cap_exceeded, a2a_cap_exceededEnterpriseThe monthly call limit is used up on /mcp/* or /a2a/*. See Licence limits.
403api_key_scopeBothA valid key lacks the scope for this operation.
403grounding_unavailableEnterpriseGrounding was required but its evidence or engine was unavailable.
403mcp_scope_denied, a2a_scope_deniedEnterpriseA plane key lacks the required scope.
404batch_not_foundBothThe batch is absent from this workspace.
404file_not_foundBothThe file is absent or belongs to another workspace; both cases deliberately look the same.
404mcp_virtual_server_not_foundEnterpriseThe virtual MCP server does not exist.
409mcp_virtual_server_duplicateEnterpriseThe virtual MCP server identifier already exists.
503workspace_credential_unavailableEnterpriseA stored workspace credential exists but cannot be used; DVARA does not fall back.
403egress_url_blockedEnterpriseAn outbound URL failed the egress or SSRF policy.

Troubleshooting​

SymptomLikely CauseFix
400 no_providerAPI key not set for the providerSet the environment variable (e.g., OPENAI_API_KEY)
403 data_residency_violationData residency policy violationConfigure routing to use providers in allowed regions
400 unsupported_response_formatProvider doesn't support the formatUse a different provider or remove response_format
400 no_capable_providerNo provider on the route supports itAdd a capable provider to the route
404 workspace_not_foundWorkspace ID does not existVerify the workspace ID via the Flightdeck
404 route_not_foundRoute ID does not existVerify the route ID via the Flightdeck
404 route_version_not_foundRoute version does not existCheck the route's version history in Flightdeck
404 report_not_foundReport ID does not existVerify the report ID via the Flightdeck
400 pii_detectedPII found and action is BLOCKRemove the value, use irreversible REDACT, or use LOG while calibrating
403 pii_tokenize_unavailableThis build has no reversible token storeUse REDACT, or run the Enterprise tokenization prerequisites
403 pii_redact_unavailableEnterprise TOKENIZE cannot mint a tokenRestore its token store or key path; inspect attempted_action, then retry
403 guardrail_blockedInjection/jailbreak/content detectedReview prompt content; change workspace guardrail action to FLAG or LOG
413 input_too_largeRequest exceeds input size limitsReduce message count, message length, or total input tokens; increase workspace limits via metadata
422 schema_validation_failedResponse doesn't match JSON schemaReview the registered schema via the Flightdeck and tighten or relax it; the registry does not yet retry on a single failure (maxRetries is reserved for a future correction-prompt flow).
400 context_window_exceededContext window full, no pruningReduce conversation length; configure pruning strategy via workspace metadata (guardrail.context.pruning-strategy)
402 budget_cap_hardHard budget limit exceededWait for the next budget period or raise the cap in Flightdeck
400 compliance_not_availableCompliance reporting is not available in this buildRun an Enterprise build that includes reporting
400 invalid_report_typeInvalid report type specifiedUse one of: SOC2, HIPAA, GDPR
400 mcp_not_availableThe requested MCP implementation is not available in this buildRun a build that includes that MCP capability
401 mcp_auth_requiredMissing Bearer token on MCP GatewayInclude Authorization: Bearer gw_<key> header
401 mcp_auth_invalidInvalid API key on MCP GatewayVerify the API key is correct
401 mcp_auth_revokedAPI key revoked on MCP GatewayGenerate a new API key
404 mcp_server_not_foundMCP server ID does not existVerify server ID via the Flightdeck
409 mcp_server_duplicateServer ID already exists for workspaceUse a different server_id or check existing servers
403 mcp_policy_deniedMCP request denied by policyCheck policy rules via the Flightdeck. Review mcp_server, mcp_tool, mcp_arg conditions.
400 mcp_upstream_rejectedThe MCP server refused the call, e.g. unknown tool or bad argumentsRead error.upstream_error.message; fix the tool name or arguments. Do not retry unchanged.
502 mcp_upstream_errorThe MCP server answered with a JSON-RPC errorRead error.upstream_error and the server's own logs for the trace_id
502 mcp_server_unavailableMCP server unreachable, timed out, or its session did not startCheck the server's address and health; the call can be retried
403 mcp_approval_unavailableApproval store unreachable, default action denyRestore Flightdeck and its approval store; retrying before then fails the same way
503 mcp_server_unavailableMCP server suspended/disabledRe-activate the server or check its upstream health in Flightdeck
429 rate_limit_exceededToo many requestsWait for Retry-After seconds, or increase limits
502 provider_errorUpstream provider returned an errorRead the hint in the error message (e.g., "invalid API key", "rate limited"). For 401: check your provider API key env var. For 429: reduce request rate. For 5xx: check the provider's status page. The gateway retries automatically.
503 provider_circuit_openToo many recent provider failuresThe gateway pauses requests to a failing provider to prevent cascading errors. It resolves automatically after a short cooldown. If it persists after restarting: check your provider API key and account status.
503 failover_capability_mismatchPrimary failed, no capable fallbackAdd more providers to the route that support the capability