When you point a client at an OpenAI-compatible inference gateway, you assume the error contract travels with the API. The reality of n4n vs openai error codes is that the gateway layers routing and fallback semantics on top of the baseline 401/429/500 shapes, and ignoring those differences ships silent failures into production.
Wire format and error object
OpenAI’s REST API returns a consistent JSON envelope on any non-2xx response:
{
"error": {
"message": "Incorrect API key provided.",
"type": "invalid_request_error",
"param": null,
"code": "invalid_api_key"
}
}
The HTTP status is the primary signal; the code field is a stable string that the SDK maps to exception classes. n4n vs openai error codes starts diverging when a gateway sits between you and multiple upstream providers. The gateway returns the same envelope shape for drop-in compatibility, but adds an extension key with gateway-specific context:
{
"error": {
"message": "Model route degraded, fallback exhausted",
"type": "api_error",
"param": null,
"code": "route_unavailable",
"extension": {
"provider": "anthropic",
"route": "claude-3-sonnet",
"attempted_fallbacks": ["openai/gpt-4o", "meta/llama-3-70b"]
}
}
}
This preserves OpenAI SDK parsing while exposing failure modes that simply do not exist in a single-vendor world.
Status code mapping
OpenAI uses 400 for malformed requests, 401 for auth, 403 for permission, 404 for model not found, 429 for rate limits, and 5xx for server issues. A gateway maps upstream provider errors to the closest OpenAI equivalent, then annotates. A provider-specific 423 (model overloaded) becomes a 503 with code: "provider_unavailable". The status code stays familiar; the code and extension carry the new information.
Capabilities: diagnostic depth
OpenAI error objects tell you what failed at the API boundary. They do not tell you which physical provider served the token because there is only one. In a multi-model gateway, the error must report why a specific route failed and whether fallback triggered.
n4n vs openai error codes shows up concretely in the extension.attempted_fallbacks array. That array lets your retry logic distinguish “all providers down” from “primary route down, secondary succeeded but returned its own error.” Without it, you blindly retry and amplify load on a degraded upstream. The gateway can also signal route_directive_ignored when a client-supplied routing hint could not be honored—a condition the first-party API will never produce.
Cost model and billing errors
OpenAI returns 429 with code: "insufficient_quota" when prepaid credits exhaust. The error carries no per-token detail; you check the dashboard. A gateway with per-token usage metering can return a similar 429 but include extension.remaining_credits and extension.last_metered_tokens so your code can shed load instead of polling a billing API.
{
"error": {
"message": "Quota exceeded for organization",
"type": "insufficient_quota",
"code": "insufficient_quota",
"extension": {
"remaining_credits": "0.00",
"last_metered_tokens": 1042
}
}
}
This is a concrete capability gap in the raw OpenAI contract. Your batch job can halt itself mid-flight when credits hit zero, rather than failing 90% through a run and leaving partial state.
Latency and throughput semantics
Error latency matters when you implement exponential backoff. OpenAI’s 429 includes a Retry-After header (seconds). The gateway honors that header from the upstream provider, but when it triggers automatic fallback, the error you receive may be the aggregated timeout after trying N routes. Another facet of n4n vs openai error codes is timeout aggregation: the extension.route_latencies_ms array shows per-attempt timing.
{
"error": {
"code": "gateway_timeout",
"extension": {
"route_latencies_ms": [1200, 1300, 1500]
}
}
}
Your client should treat this as a signal to back off longer than a single-provider 503. A naive sleep(retry_after) based on one vendor’s hint will underestimate the recovery time when three vendors were tried.
Ergonomics for client code
With the OpenAI Python SDK, you catch openai.APIError and inspect .code. Against a gateway, the same catch works, but you must read .extension safely. A defensive parser:
try:
resp = client.chat.completions.create(model="gpt-4o", messages=[...])
except openai.APIError as e:
code = e.code
ext = getattr(e, "extension", None) or {}
if code == "route_unavailable":
log.warning("gateway route failed", extra=ext)
# maybe use a different model string next time
elif code == "insufficient_quota":
handle_billing(ext.get("remaining_credits"))
else:
raise
In TypeScript the shape is identical; you just cast the error’s error field to any to read extension. The ergonomic win is zero changes to the try/except block; the cost is a documented extension schema your team must own. Skip that docs step and you will mystify the next engineer who sees route_directive_ignored in logs.
Ecosystem and SDK support
OpenAI’s error codes are documented in the official API reference and mirrored by every community SDK. Gateway-specific codes are not in that reference. n4n.ai forwards provider cache-control hints and honors client routing directives, which means its error vocabulary includes cache_write_denied or route_directive_ignored that no first-party OpenAI response will ever emit. Your SDK will not auto-handle them; you write middleware.
The OpenAPI spec published by OpenAI does not include extension. If you generate clients from that spec, the gateway’s extra fields are dropped unless you patch the schema. That is a real ecosystem tax paid by every team that adopts a multi-provider route.
Limits and rate limit reporting
OpenAI sends x-ratelimit-limit-requests, x-ratelimit-remaining-requests, x-ratelimit-reset-requests headers. The gateway aggregates these across providers behind one endpoint, so the headers reflect the least-common-denominator of your subscribed plans. A 429 from the gateway may carry extension.provider_limits with per-provider detail:
{
"error": {
"code": "rate_limit_exceeded",
"extension": {
"provider_limits": {
"openai": {"remaining": 0, "reset": 30},
"anthropic": {"remaining": 5, "reset": 10}
}
}
}
}
This lets you route the next call to the provider with headroom. Against raw OpenAI you only see your global limit and must wait for reset.
Comparison table
| Dimension | OpenAI error codes | Gateway (n4n-style) error codes |
|---|---|---|
| Wire format | {error:{message,type,param,code}} + HTTP status |
Same envelope + extension object |
| Capabilities | Single-provider diagnostics | Route, fallback, provider latency, credits |
| Cost model | insufficient_quota only |
Quota + remaining credits, last metered tokens |
| Latency signal | Retry-After header |
Retry-After + route_latencies_ms |
| Ergonomics | Native SDK exceptions | Same SDK, custom extension parsing |
| Ecosystem | Documented in API reference | Gateway-specific codes need internal docs |
| Limits reporting | Per-account ratelimit headers | Aggregated headers + per-provider breakdown |
Which to choose
Single-model, single-provider apps: Use OpenAI’s native endpoint. The error codes are stable, SDK-native, and you avoid parsing extension fields that will always be null. The n4n vs openai error codes question is moot because you never touch a gateway.
Multi-model routing with fallback needs: Point at the gateway. The extended error codes pay for themselves the first time a primary provider degrades at 2am and your code can read attempted_fallbacks to pick a different model instead of paging a human.
Cost-sensitive batch jobs: The per-token metering extensions let you halt a job when remaining_credits hits zero, rather than discovering it via a blocked account. OpenAI’s bare 429 forces a dashboard check.
High-throughput proxies: The per-provider limit breakdown in gateway errors lets you shift traffic intra-request. With OpenAI alone you only see your global limit.
The n4n vs openai error codes decision boils down to deployment topology, not familiarity. Pick the error contract that matches how many vendors you actually call.