Troubleshooting
Flightdeck actions on this page apply to the Enterprise platform. In DVARA Open Source, update the matching provider, API key, policy, route, or limit in gateway.yaml, restart DVARA, and inspect the configured local audit file. Open Source has no Flightdeck, persistent budget store, or credential-rotation UI.
Common errors when connecting SDKs to DVARA, with precise fixes. Every error response includes a trace_id — use it to look up the full request in the DVARA Flightdeck audit trail when a single line of error isn't enough.
APIConnectionError — Connection refused
openai.APIConnectionError: Connection error.
Fix: Ensure DVARA is running and accessible at the configured base URL.
curl -sS http://localhost:8080/actuator/health
# expected: {"status":"UP"}
If you're running DVARA in Docker and the SDK from the host, use http://localhost:8080/v1. If both are in the same Docker network, use the service name (e.g. http://dvara:8080/v1).
400 — no_provider
{
"error": {
"code": "no_provider",
"type": "invalid_request_error",
"message": "No provider configured for model: gpt-4o. Set OPENAI_API_KEY to register the provider.",
"trace_id": "..."
}
}
The requested model doesn't match any configured provider. The error message tells you exactly which environment variable to set. For unknown model prefixes you'll see "Check GET /v1/models for available models."
Fix: Set the provider's API key on the DVARA deployment and restart. On the Enterprise platform you can instead add the provider on Flightdeck's Providers page (owner). A credential alone does not register a provider.
401 — Unauthorized
{
"error": {
"code": "invalid_api_key",
"type": "authentication_error",
"message": "Invalid API key",
"trace_id": "..."
}
}
The type is always authentication_error; the code is one of four values so you can grep for the exact reason:
code | Meaning |
|---|---|
api_key_required | No Authorization header was sent and the data plane requires one. |
invalid_api_key | The header was sent but the key didn't match any known hash. |
api_key_revoked | The key matched a row that has been revoked. |
api_key_expired | The key matched a row whose expires_at has passed. |
Fix: Create a new key via the DVARA Flightdeck → API Keys.
Remember: the key you pass to the SDK is the DVARA key (gw_...), not the upstream provider's key.
403 — policy_denied
{
"error": {
"code": "policy_denied",
"type": "policy_violation",
"message": "Request blocked by policy",
"trace_id": "..."
}
}
Fix: A governance policy is blocking the request. Check your workspace's active policies in the DVARA Flightdeck → Policies page, or run the policy in SHADOW mode to see why it denied without blocking the request. See Routes & Policies.
403 — workspace_credential_required
{
"error": {
"code": "workspace_credential_required",
"type": "workspace_credential_required",
"message": "Workspace has no active provider credential",
"trace_id": "..."
}
}
Fix: Strict-BYOK enforcement (dvara.credentials.require-workspace-credential=true) is on and the workspace has no credential for the upstream provider. Add one from Credentials in Flightdeck, or ask a platform operator to add it for the workspace. See Credentials & BYOK.
403 — workspace_suspended
{
"error": {
"code": "workspace_suspended",
"type": "workspace_suspended",
"message": "Workspace has been suspended",
"trace_id": "..."
}
}
That envelope is the LLM plane's. Since 1.7.0 a suspension stops the other two planes as well, and each reports it in its own shape. In 1.12.0 the bodies are:
| plane | status | body |
|---|---|---|
LLM (/v1/**) | 403 | the envelope above: lowercase code, a type, a trace_id |
MCP, per-server paths (/mcp/{server}/**) | 403 | {"error":{"message":"Workspace is suspended","type":"mcp_error","code":"mcp_workspace_suspended","trace_id":"..."}} |
MCP, the native /mcp endpoint | 403 | {"error":{"code":403,"message":"Workspace is suspended","trace_id":"..."}}: the code is the HTTP status, a number |
A2A (/a2a/**) | 403 | a JSON-RPC error whose error.code is the number -32000 and whose error.message is Workspace is suspended. A2A_WORKSPACE_SUSPENDED appears only in error.data: as the reason of a google.rpc.ErrorInfo at A2A 1.0, and in lowercase as metadata.code (1.0) or data.code (0.3) |
Match on the 403 status and on the plane's code: workspace_suspended on the LLM plane, mcp_workspace_suspended on MCP per-server paths, and the code in error.data on A2A. Do not match on type; the planes set it differently.
Fix: The workspace is administratively suspended — trial-cliff expiry, chronic-abuse sweep, scheduled deletion, or manual operator action. Cancel the pending deletion from the workspace account page, move to a paid plan, or contact the operator to lift the suspension.
Lifting or applying a suspension is not instantaneous, and the planes do not change together. From 1.8.2 a suspension reaches each Gateway on the next signed configuration bundle or revocation list, about 10 to 15 seconds at the default settings, so there is a propagation window. An earlier measured run, before 1.8.2, had the MCP and A2A planes refusing within 12 seconds of the change while the LLM plane caught up before 57 seconds. Expect up to about a minute, and do not read "the LLM plane still answers" in the first few seconds as the suspension having failed.
Each plane writes a WORKSPACE_SUSPENDED_BLOCK audit event for each refused request. The payload's plane field names the plane (mcp or a2a; the LLM plane's event has no plane field). One gap remains: the native /mcp endpoint refuses a suspended workspace's request with its own check, before the MCP governance chain runs, so that refusal leaves no audit event. Count those from the 403 responses.
403 — guardrail_blocked
{
"error": {
"code": "guardrail_blocked",
"type": "guardrail_violation",
"message": "Request blocked by guardrail",
"trace_id": "..."
}
}
Fix: A guardrail detector fired at or above the configured risk threshold and the workspace's action is BLOCK. Switch the workspace action to FLAG while you tune patterns, raise the risk threshold, or fix the input. See Guardrails.
400 — pii_detected
{
"error": {
"code": "pii_detected",
"type": "pii_violation",
"message": "Request contains PII",
"trace_id": "..."
}
}
Fix: PII was detected in the request and the workspace's PII action is
BLOCK. Remove the sensitive value, use irreversible REDACT, use Enterprise
TOKENIZE when the value must be recoverable, or switch to LOG while you
calibrate detection. LOG is the default and forwards the value unchanged.
Don't disable PII enforcement to "make it work" — investigate the source of
the sensitive data. See PII governance.
413 — input_too_large
{
"error": {
"code": "input_too_large",
"type": "input_size_error",
"message": "Request exceeds maximum input size",
"trace_id": "..."
}
}
Fix: The request exceeds one of guardrail.max-input-tokens, guardrail.max-messages-per-request, or guardrail.max-message-length (OWASP LLM06 Unbounded Consumption defense). Either reduce the input or raise the per-workspace override (Workspace.metadata["guardrail.max-input-tokens"] etc.) if the workload legitimately needs more.
402 — budget_cap_hard
{
"error": {
"code": "budget_cap_hard",
"type": "budget_exceeded",
"message": "Workspace budget exceeded",
"trace_id": "..."
}
}
Fix: The workspace has hit its hard budget cap. Either raise the cap in DVARA Flightdeck under Cost → Budget Caps, or wait for the next billing period. The FinOps dashboard shows current spend versus cap.
429 — rate_limit_exceeded
{
"error": {
"code": "rate_limit_exceeded",
"type": "rate_limit_error",
"message": "Rate limit exceeded for this API key",
"trace_id": "..."
}
}
Fix: The API key has hit its configured rate limit. Back off and retry with exponential backoff, or raise the per-key rate limit via the DVARA Flightdeck.
502 — provider_error
{
"error": {
"code": "provider_error",
"type": "provider_error",
"message": "OpenAI API error 401 (invalid API key - check your provider credentials)",
"trace_id": "..."
}
}
Fix: The upstream provider returned an error. The message includes the
upstream status code and a hint. When fallback is enabled, a request that
matched a route fails over only along that route's own fallbacks list. A
matched route with no fallbacks does not fail over. Only a request that
matched no route falls back to other registered providers that accept the same
model identifier and requested capabilities. A route's chain tries at most
fallback.max-attempts targets (default 3), and none starts after
fallback.deadline (default 60s). The most common cause is a wrong or revoked
provider credential; rotate it through Credentials.
See Resilience and failover
for the exact eligibility and candidate rules.
503 — provider_circuit_open
{
"error": {
"code": "provider_circuit_open",
"type": "provider_unavailable",
"message": "Provider circuit open",
"trace_id": "..."
}
}
Fix: DVARA's circuit breaker tripped after repeated upstream failures. Wait for the half-open probe or check the upstream provider's status page. Automatic fallback helps only when another registered provider accepts the same request; registering a provider does not create a cross-provider model mapping.
Where to look next
- Every error includes a
trace_id. Paste it into the search on DVARA Flightdeck's Governance → Audit page to see the full request, which filter rejected it, and the upstream status. - Streaming responses terminate with
finish_reason: "content_filter"on the final chunk when a guardrail fires mid-stream. Inspect the chunk'sfinish_reasonin your stream loop to detect this case (rather than relying on a header — SSE responses don't carry trailing custom headers across all client SDKs). - For policy debugging, enable policy shadow mode: denials still log but requests pass through. See Routes & Policies.
Next steps
- Back to Integrations overview.
- Check out language-specific guides: Python, JavaScript / TypeScript, Java.
- Correlate failures across your stack with DVARA headers.