Skip to main content
Every gateway error is returned in the OpenAI-compatible envelope:
This matches what the openai Python and TypeScript SDKs, plus the Anthropic SDK (which parses a superset), expect. Existing client code raises its usual typed exceptions unchanged.

Response headers

Errors (like successes) always carry:
  • X-LangWatch-Request-Id: grq_<ULID>, use this when filing support tickets.
  • X-LangWatch-Provider, present when the error originated from an upstream provider (absent for gateway-internal errors).

Type enum

Budget-warning headers (not errors)

These are soft signals on successful responses:
  • X-LangWatch-Budget-Warning: <scope>:<pct>, a budget scope is over its soft threshold. Multiple can be present.
A warn breach never turns into an error envelope; it’s only a header.

Examples

Invalid key

Budget exceeded

Blocked tool

Upstream timeout after fallback exhaustion

Streaming errors

For SSE streaming, a terminal event: error frame carries the same envelope and the stream ends:
Clients that receive chunks and then an error frame should treat the response as incomplete (partial) and X-LangWatch-Request-Id still identifies the session in traces.

Mid-stream code values

Once bytes are flowing, the HTTP status is already 200, so the distinguishing signal for clients is the code field inside the terminal frame:
The type on a streaming terminal frame always reflects the category (provider_error, guardrail_blocked), clients keying off type will already have a usable classification. The code is the granular discriminator if you need it (for example, a retry policy that distinguishes “upstream flaked, retry with a different VK” from “guardrail policy said no, don’t retry”).