Every error the gateway itself returns is JSON with an error code and a message. Errors from the provider are passed through unchanged; the gateway's own always carry one of the codes below. The gateway also logs each refusal on standard output (docker logs openwaf-egress).
{"error": "egress_blocked", "message": "Agent \"my-support-agent\" is not permitted to access target \"openai\""}All error codes
| Status | error | Cause |
|---|---|---|
| 400 | body_read_error | The request body could not be read (client disconnected or broken transfer). |
| 401 | unauthorized_agent | No agent matches: the name in the URL or in X-OpenWAF-Agent is not in agents, or on /v1/proxy/… no agent has the token sent. |
| 401 | token_required | The agent has a token and the request has no Authorization header. |
| 401 | invalid_token | The Authorization: Bearer value is not the agent's token. |
| 403 | egress_blocked | The target exists but is not in the agent's allowed_targets. |
| 403 | ssrf_blocked | The target's host resolves to a private or reserved address, or does not resolve. |
| 403 | injection_detected | A prompt-injection detector matched the body (enforce_injection). |
| 403 | data_leak_blocked | A data-leak pattern matched the body (block_dlp). |
| 404 | invalid_route | The path is not /v1/agent/<agent>/proxy/<target>/…, /v1/proxy/<target>/… or /health. |
| 404 | unknown_target | The target alias is not in targets. |
| 413 | body_too_large | The body is over 8 MiB, or, with inspection on, its text outside inline media is over 1 MiB. |
| 500 | invalid_upstream_url, request_creation_failed | The target's base_url cannot be parsed, or the outgoing request cannot be built. |
| 502 | credential_resolution_failed | The key could not be read from OpenBao or Vault. |
| 502 | upstream_error | The provider could not be reached (DNS, connection, TLS or timeout). |
401: the agent is not identified
unauthorized_agent: check the spelling of<agent>in the base URL against the keys ofagents. Names are case-sensitive.token_required: the SDK sends the key inAuthorization: Bearer. If it sends it in another header (for examplex-api-key), the gateway does not see it.invalid_token: the placeholder in the agent does not matchtokenin the configuration. Remember that a restart is needed after editing the file.
403: the request was refused
egress_blocked: add the target alias to the agent's allowed_targets.
ssrf_blocked: the message says which address was refused, for example destination IP 169.254.169.254 is private or reserved. A provider hostname that resolves to a private address on your network (split DNS, a local proxy) is refused too. A resolution error also lands here: check DNS from inside the container.
injection_detected: the response lists each hit with its detector ID, Label and the matched Snippet:
{"agent":"my-support-agent","detections":[{"ID":"pi.override.en","Label":"Instruction override","Snippet":"Ignore all previous instructions"}],"error":"injection_detected","message":"Request body contains prompt injection or adversarial pattern","target":"openrouter"}Look at the snippet: it is the text that matched, at most 160 bytes. If it came from a document or a web page the agent read, the agent is doing its job by not acting on it. Detectors cannot be turned off one by one in v0.1.1; for an agent that must process such text, set enforce_injection to false for that agent only.
data_leak_blocked: the response lists each type (credit_card, private_key, api_key) with a description. Card numbers are shown with the first and last four digits only. Remove the data from the prompt, or set block_dlp to false for that agent.
413: the body is too large
The gateway never cuts a body and never forwards part of it uninspected. With enforce_injection or block_dlp on, the text must fit 1 MiB. Inline media does not count: data:image/…;base64,… URIs (audio and video too) and JSON "data" members of at least 1 KiB of bare base64 (OpenAI input_audio, Gemini inlineData, Anthropic base64 sources). Send large files by URL or through the provider's file API, or split the request. No body may exceed 8 MiB.
502: OpenBao or the provider failed
credential_resolution_failed: the log line says which secret failed, without its value:
[EGRESS] Failed resolving secret agents/support:OPENROUTER_API_KEY for agent my-support-agent: vault error 403 reading agents/supportobtaining vault token: approle login failed with status …: wrongrole_idorsecret_id, or the secret ID expired.vault error 403: the AppRole policy does not allowreadon<kv_mount>/data/<path>, often becausekv_mountorpathis wrong. With KV v2 the mount is not part ofpath.vault error 404: there is no secret at that path.key "…" not found in path "…": the secret exists but has no field with that name.- A connection or certificate error: check
addrandca_file, and that/healthreports"openbao": true.
upstream_error: the message includes the error. Check the target's base_url, DNS and outbound access from the container. The gateway waits up to 5 minutes for the provider's response headers and 15 minutes for a whole exchange, streamed body included.
The provider answers 401 or 403
The error comes from the provider, passed through. Usual causes:
- The target has no entry in the agent's
credential_mapping, so the request reached the provider without a key. - The key in OpenBao is wrong, revoked or rotated less than five minutes ago (the gateway caches secrets for five minutes).
- The target's
auth_headerorauth_prefixdoes not match what the provider expects (Anthropic:x-api-keywith no prefix; Gemini:x-goog-api-key). Keys in the query string (?key=) are not injected.
The agent gets a 3xx
The gateway does not follow redirects; the provider's 3xx reaches the agent as it is. Point base_url at the final URL the provider documents (for example https:// instead of http://).
/health says "openbao": false
Either openbao.addr is not set, or the gateway could not get 200 or 429 from <addr>/v1/sys/health within three seconds: the server is sealed or unreachable, or its certificate is not trusted (set ca_file). Requests to targets with a credential_mapping will fail with 502 until it is fixed.
Written from github.com/openwaf-dev/[email protected] (external link).