Error Handling
All errors from Dvara use a consistent JSON envelope, regardless of the source (validation, provider, internal).
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"
}
}
| Field | Type | Description |
|---|---|---|
message | string | Human-readable error description |
type | string | Error category (see table below) |
code | string | Machine-readable error code |
param | string | Field name that caused the error (validation only) |
trace_id | string | 32-character hex trace ID for debugging |
HTTP Status Codes
| Status | type | code | When |
|---|---|---|---|
| 400 | invalid_request_error | validation_error | Missing required field (e.g., model, messages) |
| 400 | invalid_request_error | no_provider | No provider configured for the requested model |
| 400 | invalid_request_error | invalid_request | Malformed JSON body or invalid response_format |
| 400 | invalid_request_error | unsupported_response_format | Provider doesn't support response_format |
| 400 | invalid_request_error | no_capable_provider | No provider on route supports the requested format |
| 400 | invalid_request_error | no_regional_provider | No provider available in the required region |
| 400 | invalid_request_error | credential_not_found | Required provider credential is not configured |
| 400 | invalid_request_error | compliance_not_available | Compliance reports require enterprise license |
| 400 | invalid_request_error | invalid_report_type | Invalid compliance report type |
| 400 | invalid_request_error | mcp_not_available | MCP features require enterprise license |
| 400 | pii_violation | pii_detected | PII detected in request and action is BLOCK |
| 400 | invalid_request_error | context_window_exceeded | Context window exceeded with no pruning strategy |
| 402 | budget_exceeded | budget_cap_hard | Hard budget limit exceeded |
| 403 | guardrail_violation | guardrail_blocked | Guardrail violation detected (injection, jailbreak, content) |
| 403 | data_residency_error | data_residency_violation | Request violates data residency policy |
| 413 | input_size_error | input_too_large | Request exceeds input size limits (messages, length, tokens) |
| 422 | invalid_request_error | schema_validation_failed | Output schema validation failed after max retries |
| 401 | authentication_error | invalid_internal_secret | Invalid or missing X-Internal-Secret header |
| 404 | not_found_error | tenant_not_found | Tenant ID does not exist |
| 404 | not_found_error | api_key_not_found | API key ID does not exist or belongs to another tenant |
| 404 | not_found_error | route_not_found | Route ID does not exist |
| 404 | not_found_error | route_version_not_found | Route version does not exist |
| 404 | not_found_error | report_not_found | Compliance report ID does not exist |
| 404 | not_found_error | mcp_server_not_found | MCP server ID does not exist |
| 409 | duplicate_error | mcp_server_duplicate | MCP server ID already exists for this tenant |
| 429 | rate_limit_error | rate_limit_exceeded | Rate limit exceeded. Includes Retry-After header. |
| 502 | provider_error | provider_error | Upstream provider returned an error (4xx/5xx) |
| 503 | provider_unavailable | provider_circuit_open | Provider circuit breaker is open |
| 503 | provider_unavailable | failover_capability_mismatch | Failover blocked — no capable fallback available |
| 500 | gateway_error | gateway_error | Unexpected internal error |
MCP Proxy Error Codes (port 8070)
The MCP proxy uses a separate error envelope with mcp_error type. All codes are lowercased with mcp_ prefix.
| Status | Type | Code | Description |
|---|---|---|---|
| 401 | mcp_error | mcp_auth_required | Missing Bearer token on MCP proxy request |
| 401 | mcp_error | mcp_auth_invalid | Invalid API key |
| 401 | mcp_error | mcp_auth_revoked | API key has been revoked |
| 404 | mcp_error | mcp_server_not_found | MCP server ID not found for tenant |
| 503 | mcp_error | mcp_server_unavailable | MCP server is suspended or disabled |
| 403 | mcp_error | mcp_policy_denied | MCP request denied by policy rule |
| 502 | mcp_error | mcp_upstream_error | Upstream MCP server returned an error or unreachable |
| 400 | mcp_error | mcp_not_available | MCP proxy requires enterprise license |
| 500 | mcp_error | mcp_internal_error | Unexpected internal error in MCP proxy |
Error Examples
Validation Error — Missing Model
curl -X POST http://localhost:8080/v1/chat/completions \
-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 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. Supported formats: [text]",
"type": "invalid_request_error",
"code": "unsupported_response_format"
}
}
Tenant Not Found
{
"error": {
"message": "Tenant not found: t-999",
"type": "not_found_error",
"code": "tenant_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": "Per-key request rate limit exceeded",
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"trace_id": "a6783439db1f46a6bfed511a0011e955"
}
}
Provider Error
{
"error": {
"message": "Provider openai returned HTTP 500: internal server error",
"type": "provider_error",
"code": "provider_error",
"trace_id": "b7894561cd2e4f38a1cc820d1f1f5044"
}
}
Circuit Breaker Open
{
"error": {
"message": "Provider openai is temporarily unavailable (circuit breaker open)",
"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. Tenant 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 after 2 retries: [$.name: required property missing]",
"type": "invalid_request_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": "invalid_request_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"
}
}
Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
400 no_provider | API key not set for the provider | Set the environment variable (e.g., OPENAI_API_KEY) |
401 invalid_internal_secret | Missing/wrong X-Internal-Secret | Set the correct gateway.internal.secret value or header |
400 no_regional_provider | No provider in required region | Add a provider in the target region to the route |
400 credential_not_found | Credential missing at runtime | Set the provider API key or check SecretProvider configuration |
403 data_residency_violation | Data residency policy violation | Configure routing to use providers in allowed regions |
400 unsupported_response_format | Provider doesn't support the format | Use a different provider or remove response_format |
400 no_capable_provider | No provider on the route supports it | Add a capable provider to the route |
404 tenant_not_found | Tenant ID does not exist | Verify the tenant ID via GET /admin/v1/tenants |
404 route_not_found | Route ID does not exist | Verify the route ID via GET /admin/v1/routes |
404 route_version_not_found | Route version does not exist | Check version history via GET /admin/v1/routes/\{id\}/versions |
404 report_not_found | Report ID does not exist | Verify the report ID via GET /admin/v1/reports |
400 pii_detected | PII found and action is BLOCK | Remove PII from request, or change tenant PII action to REDACT or LOG |
403 guardrail_blocked | Injection/jailbreak/content detected | Review prompt content; change tenant guardrail action to FLAG or LOG |
413 input_too_large | Request exceeds input size limits | Reduce message count, message length, or total input tokens; increase tenant limits via metadata |
422 schema_validation_failed | Response doesn't match JSON schema | Review schema config via GET /admin/v1/schemas; adjust correction prompt or increase max retries |
400 context_window_exceeded | Context window full, no pruning | Reduce conversation length; configure pruning strategy via tenant metadata (guardrail.context.pruning-strategy) |
402 budget_cap_hard | Hard budget limit exceeded | Wait for next budget period or increase budget via PUT /admin/v1/budgets/\{id\} |
400 compliance_not_available | Enterprise license not active | Set GATEWAY_ENTERPRISE_LICENSE_KEY to a valid signed JWT (see license-generator) |
400 invalid_report_type | Invalid report type specified | Use one of: SOC2, HIPAA, GDPR |
400 mcp_not_available | MCP features require enterprise | Set GATEWAY_ENTERPRISE_LICENSE_KEY to a valid signed JWT (see license-generator) |
401 mcp_auth_required | Missing Bearer token on MCP proxy | Include Authorization: Bearer gw_<key> header |
401 mcp_auth_invalid | Invalid API key on MCP proxy | Verify the API key is correct |
401 mcp_auth_revoked | API key revoked on MCP proxy | Generate a new API key |
404 mcp_server_not_found | MCP server ID does not exist | Verify server ID via GET /admin/v1/mcp/servers |
409 mcp_server_duplicate | Server ID already exists for tenant | Use a different server_id or check existing servers |
403 mcp_policy_denied | MCP request denied by policy | Check policy rules via GET /admin/v1/policies. Review mcp_server, mcp_tool, mcp_arg conditions. |
502 mcp_upstream_error | Upstream MCP server error | Check MCP server health via /admin/v1/mcp/servers/\{id\}/health |
503 mcp_server_unavailable | MCP server suspended/disabled | Re-activate the server via PUT /admin/v1/mcp/servers/\{id\} |
429 rate_limit_exceeded | Too many requests | Wait for Retry-After seconds, or increase limits |
502 provider_error | Upstream provider issue | Check provider status page; the gateway will retry automatically |
503 provider_circuit_open | Repeated provider failures | Wait for the circuit breaker to transition to half-open (default: 30s) |
503 failover_capability_mismatch | Primary failed, no capable fallback | Add more providers to the route that support the capability |