Handle Policy Blocks and Gateway Errors
Gateway-generated failures use the public error envelope. Some request families can preserve an upstream status and error body. This page shows how to distinguish stable Verdictan fields from provider-specific details.
Public error envelope
Verdictan returns JSON in this shape:
{
"error": {
"message": "Request blocked by policy: prompt_injection.detected",
"type": "invalid_request_error",
"param": null,
"code": "content_policy_violation"
}
}
Use error.type and error.code for application logic. Use error.message as
descriptive text for the user.
Frequent error categories
| Condition | Status | error.type | error.code |
|---|---|---|---|
| Buffered request or response blocked by policy | 400 | invalid_request_error | content_policy_violation |
| Header/body session ID mismatch | 422 | invalid_request_error | session_id_mismatch |
| Missing, invalid, revoked, or expired API token | 401 | authentication_error | invalid_api_token or tokens.expired |
| Token budget exhausted | 402 | cost_budget_exceeded | tokens.budget_exhausted |
| Token request limit exhausted | 403 | access_denied | tokens.request_limit_exhausted |
| Gateway-generated provider failure | route-specific 4xx or 5xx | provider_error | can be null |
| Gateway runtime failure | 500 | internal_error | can be null |
Policy block example
For a non-streaming request, a policy block returns HTTP 400 and the standard
envelope:
{
"error": {
"message": "Request blocked by policy: prompt_injection.detected",
"type": "invalid_request_error",
"param": null,
"code": "content_policy_violation"
}
}
Handle this case as a governed refusal, not as a transport failure.
For a streaming request, the HTTP stream can start before an output policy
blocks the response. Then, the status stays 200. The gateway sends the
policy error in the SSE body. Examine the stream events. Do not use only the
initial status.
Invalid request example
Validation failures usually identify an incorrect payload shape or request option:
{
"error": {
"message": "Body session_id must match the configured session header when both are present",
"type": "invalid_request_error",
"param": null,
"code": "session_id_mismatch"
}
}
Correct the client payload. Then, retry the request.
Provider failures
Provider failures have different shapes. Some request families preserve the
provider status and body. Other paths create a provider_error envelope. The
request family and failure location control this behavior.
Retry a provider failure only when the status lets you retry. The operation must be idempotent. The workflow must be able to wait. Do not change a failed provider call to a silent success.
How to debug the failure
- Run
verdictan events tail --since 10m --json. - Reproduce the request.
- For a policy failure, run
verdictan events tail --since 10m --verdict blocked --json. - Match the Event request ID to the client response.
- Use the Event as delivered control-plane evidence.
- Open History only when you enable capture and request or session details.
- Use Trail or exports when you must send an evidence package.
Application guidance
- Select behavior from
error.typeanderror.code, not from free-form message text. - Do not retry
invalid_request_errororcontent_policy_violationblindly. - For provider errors, examine the HTTP status and returned body. The provider can supply the body.
- Retry only when the request is idempotent and your caller can wait.
- Log the request identifier and returned error fields together. This helps you connect application logs to Verdictan evidence.