
Fix OpenRouter 429 "Provider Returned Error": Rate Limits, Upstream Providers, and Fallback Options

These two errors look similar in your logs but have different root causes:
- 429 Too Many Requests: your request was rejected because a rate limit was hit
- Provider returned error: OpenRouter accepted your request but the upstream model provider (OpenAI, Anthropic, Google, etc.) returned an error
Mixing them up leads to wrong fixes. This guide helps you isolate the cause and choose the right response.
TL;DR
- A 429 from OpenRouter itself means you hit OpenRouter's rate limit or quota.
- A "provider returned error" means the upstream provider rejected the request — not OpenRouter.
- Check response headers and error body to distinguish the two.
- The fix is different: OpenRouter 429 needs key/tier changes; provider errors need upstream diagnosis or route changes.
- For production workloads, design fallback before the error happens.
Step 1: Read the error response carefully
When you get an error, look at these three things:
| Signal | Where to find it | What it tells you |
|---|---|---|
| HTTP status code | Response status | 429 = rate limit; 502/503 = upstream failure |
| Error message body | error.message in JSON response | Often says "provider returned error" or gives a specific rate limit message |
| Response headers | x-ratelimit-remaining, retry-after | Whether OpenRouter itself is throttling you |
A typical OpenRouter 429 looks like:
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please slow down."
}
}A typical provider returned error looks different:
{
"error": {
"code": 502,
"message": "Provider returned error: [upstream error details]"
}
}The distinction matters because they require different fixes.
Step 2: Identify the error source
Use this decision tree:
Request failed
├── HTTP 429 + OpenRouter rate limit message
│ → Cause: OpenRouter-level rate limit
│ → Fix: reduce request rate, upgrade tier, or add delay
│
├── HTTP 429 + "provider returned error" in message
│ → Cause: upstream provider rate limit passed through
│ → Fix: check provider quota, switch model, or add fallback route
│
├── HTTP 502/503 + "provider returned error"
│ → Cause: upstream provider outage or transient failure
│ → Fix: retry with backoff, switch provider, or use fallback
│
└── HTTP 400/401 + error message
→ Cause: bad request, invalid key, or model not found
→ Fix: check API key, model ID, and request formatStep 3: Fix OpenRouter-level 429
If the 429 is from OpenRouter itself (not passed through from a provider), check these in order:
3.1 Check your current rate limit tier
OpenRouter applies rate limits based on your account tier. Free tier users have significantly lower limits than paid users.
3.2 Reduce request rate
If you are sending requests faster than your tier allows:
import asyncio
import random
async def call_with_backoff(make_request, max_retries=5):
for attempt in range(max_retries):
try:
return await make_request()
except Exception as e:
if "429" in str(e) and attempt < max_retries - 1:
# Respect retry-after if present, otherwise use jittered backoff
delay = min(30, (2 ** attempt) + random.random())
await asyncio.sleep(delay)
else:
raise3.3 Spread traffic across time
Agent workloads often create burst patterns. Instead of sending 50 requests simultaneously:
- Use a semaphore to cap concurrency
- Add a small delay between batches
- Separate foreground and background queues
Step 4: Fix upstream provider errors
If the error message contains "provider returned error", the problem is upstream. OpenRouter forwarded your request, but the model provider rejected it.
4.1 Common upstream causes
| Upstream cause | What you see | How to verify |
|---|---|---|
| Provider rate limit | 429 passed through | Check if the same model works with lower request rate |
| Provider outage | 502/503 passed through | Check provider status page (e.g., status.openai.com) |
| Model deprecated or unavailable | 404 or model not found | Verify model ID is still valid on OpenRouter model list |
| Region restriction | 403 or access denied | Some providers restrict access by geography |
| Input too large | 400 with context/token message | Check if your input exceeds the model's context window |
4.2 Switch to a different provider route
OpenRouter routes requests to upstream providers. If one provider is rate-limiting you, the same model might be available through a different provider path.
Check whether:
- The model has multiple provider options on OpenRouter
- You can configure provider preferences in your request
- A fallback model with similar capability is available
4.3 Add retry logic that distinguishes error types
Do not retry all errors the same way:
async def smart_retry(make_request, max_retries=3):
for attempt in range(max_retries):
try:
return await make_request()
except Exception as e:
error_msg = str(e)
# Do NOT retry: bad request, auth error, model not found
if any(code in error_msg for code in ["400", "401", "404"]):
raise
# Retry with backoff: rate limit or provider error
if any(code in error_msg for code in ["429", "502", "503"]):
delay = min(30, (2 ** attempt) + random.uniform(0, 1))
await asyncio.sleep(delay)
else:
raiseStep 5: Design fallback before it happens
In production, the question is not whether upstream errors will occur — they will. The question is whether your system degrades gracefully or crashes.
Fallback checklist
| Fallback layer | What to implement | Why |
|---|---|---|
| Retry with backoff | Jittered exponential backoff respecting retry-after | Handles transient failures without amplifying load |
| Model fallback | If primary model fails, route to a capable alternative | Keeps the workflow running when one model path is down |
| Provider fallback | If one provider returns errors, try a different route | Reduces single-provider dependency |
| Queue + circuit breaker | Stop sending to a failing path after N consecutive failures | Prevents retry storms from making the problem worse |
| Graceful degradation | Smaller context, cheaper model, or cached response | Better than a hard failure for the end user |
When to consider a unified API gateway
If you are building fallback logic on top of OpenRouter to handle upstream failures, you are effectively building a routing layer on top of a routing layer.
At that point, it may be simpler to use a gateway that handles provider routing, fallback, and model selection as a built-in feature rather than application-level code.
- Routes across providers automatically
- Returns the actual model used in the response
- OpenAI-compatible request shape — no code rewrite needed
- No separate routing fee
curl https://api.evolink.ai/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "evolink/auto",
"messages": [
{"role": "user", "content": "Your prompt here"}
]
}'This does not eliminate the need for client-side retry logic, but it moves provider selection and fallback out of your application code.
Error cause tree (reference)
OpenRouter request failed
│
├── 429 from OpenRouter
│ ├── Free tier limit → upgrade account
│ ├── Burst traffic → add concurrency control
│ └── Sustained high volume → check tier limits
│
├── "Provider returned error"
│ ├── Upstream 429
│ │ ├── Provider rate limit → reduce rate or switch provider
│ │ └── Shared quota exhausted → check org-level limits
│ ├── Upstream 502/503
│ │ ├── Provider outage → check status page, wait or switch
│ │ └── Transient failure → retry with backoff
│ └── Upstream 400
│ ├── Context too long → truncate or switch model
│ ├── Invalid parameters → check API docs
│ └── Model deprecated → verify model ID
│
└── Other errors
├── 401 → invalid API key
├── 404 → model not found
└── Network error → check connectivityWhat to do next
- Check your current error: Use Step 2 to identify whether it is an OpenRouter 429 or a provider error.
- Apply the targeted fix: Do not apply rate-limit fixes to provider errors or vice versa.
- Add structured retry logic: Distinguish retryable and non-retryable errors in code.
- Design fallback before you need it: Production systems should never depend on a single upstream path.
Related articles
- How to Reduce 429 Errors in Agent Workloads — deeper patterns for agent-specific burst traffic
- Best OpenRouter Alternatives in 2026 — compare routing options when OpenRouter limits are a recurring problem
- Best AI API Platform for Production Reliability — framework for choosing a reliable production API platform
FAQ
What does "provider returned error" mean on OpenRouter?
It means OpenRouter received your request and forwarded it to the upstream model provider, but the provider returned an error. The error is not from OpenRouter itself — it is from OpenAI, Anthropic, Google, or whichever provider serves that model.
Is a 429 from OpenRouter the same as a 429 from the upstream provider?
No. An OpenRouter-level 429 means you hit OpenRouter's own rate limits. A provider-level 429 passed through as "provider returned error" means the upstream provider rejected the request. The fixes are different.
Should I retry on "provider returned error"?
It depends on the error type. If the upstream returned 502/503 (transient failure), retry with backoff is reasonable. If it returned 400 (bad request) or 404 (model not found), retrying will not help — fix the request instead.
How do I know if the problem is my API key, my quota, or the provider?
Check in this order: (1) Is your API key valid? Try a simple test request. (2) Check your OpenRouter dashboard for quota and rate limit usage. (3) If your key and quota are fine, the error is likely from the upstream provider — check the error message for details.
Can a unified API gateway eliminate provider errors?
No gateway can prevent upstream providers from failing. But a gateway with built-in routing and fallback can automatically switch to an alternative provider or model when one path fails, reducing the impact on your application.
When should I switch from OpenRouter to another routing solution?
Consider switching when: (1) provider errors are a recurring production problem, (2) you need fallback logic that OpenRouter does not provide, (3) your workload spans multiple modalities (text + image + video), or (4) you want routing decisions managed at the gateway level rather than in application code.


