Education

Fixing "Provider Returned Error" on OpenRouter

"Provider returned error" is a wrapper, not a diagnosis. Here's how to tell rate limits, provider outages, and malformed requests apart, and fix each one fast.

BSBrittany Seales· Marketing5 min read
Fixing OpenRouter Error - SayGm blog header graphic

"Provider returned error" is one of the most common failures developers hit when building on OpenRouter, and it's also one of the least informative on its own. The message tells you almost nothing about what actually went wrong, because it's a wrapper: OpenRouter is reporting that the upstream model provider rejected or failed the request, not that OpenRouter itself broke. This shows up constantly in Cursor, Cline, Continue.dev, and any custom agent calling the chat completion api, provider returned error and its close cousins are generic enough to hide several unrelated root causes behind one string.

This post walks through what's actually happening under that message, how to tell the causes apart, and what to do about each one, including the option of routing through a gateway with a smaller, individually monitored catalog instead of debugging blind across hundreds of providers.

Table of Contents

What "Provider Returned Error" Actually Means

OpenRouter 400 provider returned error message example

OpenRouter sits between your application and dozens of upstream model providers. When a request fails, OpenRouter's own error documentation explains that it returns a JSON error object with a code, a message, and a metadata field, and that field is where the real story lives. "Provider returned error" specifically means the failure happened on the provider's side of that boundary after OpenRouter successfully forwarded your request, which is why retrying the exact same call sometimes works and sometimes doesn't: the cause is usually transient, on someone else's infrastructure, not a bug in your code.

The Most Common Causes

Upstream rate limits (429)

The provider behind the model you're calling, not OpenRouter itself, has throttled the request. This is common on free-tier or heavily discounted model routes during peak load.

Provider outages (502/503)

The upstream provider is down or degraded. These are almost always transient and resolve within minutes, but they'll still surface as a hard failure if your code doesn't retry.

Malformed requests that pass gateway validation

OpenRouter's own validation is looser than each provider's, so a request can pass through the gateway cleanly and still fail once it reaches the provider. A frequent real-world example is a mismatched tool_use/tool_result pair in a multi-turn agent conversation: OpenRouter accepts the payload, the provider rejects it.

Content moderation blocks

Some providers apply their own content filtering independently of OpenRouter's, so a prompt that's fine by OpenRouter's standards can still get blocked at the model level.

How to Diagnose the Real Cause

Don't treat every instance of this error the same way. Three checks separate the causes fast:

  1. Read the HTTP status code alongside the message. A 429 plus "provider returned error" means an upstream rate limit; a 502 or 503 means a provider outage; a 400 usually points to a malformed request.
  2. Inspect error.metadata.raw and error.metadata.provider_name in the response body. This is the original error the provider sent, and it names the provider, which narrows the search immediately.
  3. Check whether it's reproducible. A one-off failure that succeeds on retry is almost always transient (rate limit or outage). A failure that repeats identically every time is almost always a malformed request or a model-specific limitation.

How to Fix It

  • For rate limits and outages: add retry logic with exponential backoff, and configure a fallback model so a single provider's bad day doesn't take your whole app down with it. This is worth checking explicitly rather than assuming your tooling already handles it: some Claude router and any router claude code setups have shipped with this exact string missing from their retryable-error patterns, so the agent aborts instead of retrying (see this reported case for what that looks like in practice).
  • For malformed requests: validate tool call and message structure before sending, particularly in multi-turn agent loops where a dropped tool_use block is the single most common trigger.
  • For content moderation blocks: rephrase the prompt, or route that specific request to a different model with different filtering behavior.
  • If it persists across retries and across providers: check OpenRouter's status page before assuming the problem is on your end.
  • If this is a recurring problem rather than an occasional one: the underlying cause is scale, hundreds of upstream providers each with their own rate limits and outage patterns. Routing the same request through SayGm's smaller, individually monitored catalog removes most of that variance rather than requiring you to debug around it every time.

Why This Error Happens Less on SayGm's Smaller Catalog

Part of what makes this error hard to fully eliminate on OpenRouter is scale: routing across 300+ models and dozens of upstream providers means dozens of different rate-limit policies, moderation systems, and outage patterns to account for. Every one of those is a place where "provider returned error" can originate, and none of them are something OpenRouter itself controls.

SayGm model leaderboard showing GPQA Diamond and MATH-500 scores with live pricing

SayGm takes a narrower approach on purpose:

OpenRouterSayGm
Catalog size300+ models, dozens of upstream providers~30 curated frontier and open-weight models
Failure surfaceBroad: every upstream provider's own limits and outages pass throughNarrower: fewer providers, each integrated and monitored individually
Switching cost-Same OpenAI-compatible base URL, drop-in replacement

Same category of gateway, an OpenAI-compatible base URL you can drop into existing code, just with a smaller, more predictable surface area to debug when something does go wrong. See the integrations guide for connecting existing tools like Cursor, Cline, and Claude Code.

FAQ

Does OpenRouter retry failed requests automatically?

Only if you've configured a fallback model in your request. By default, a provider error is returned to your application to handle, it isn't silently retried on OpenRouter's side.

Is "provider returned error" the same as a 429 rate limit?

Not necessarily. A 429 directly from OpenRouter means you've hit OpenRouter's own limit. A 429 wrapped inside "provider returned error" means the upstream provider's limit was hit, which is a different fix (switch models or reduce load on that specific provider, not upgrade your OpenRouter tier).

Why does the same request fail sometimes and succeed other times?

That pattern is the clearest signal you're looking at a transient cause, an upstream rate limit or a brief outage, rather than something wrong with the request itself.

Final Thoughts

"Provider returned error" is a generic wrapper, not a diagnosis, and treating it as one wastes debugging time. Read the status code and metadata first, separate transient causes from structural ones, and build retry and fallback logic for the transient half, since that's most of what you'll hit in practice.

If you're tired of debugging which of 300+ upstream providers is having a bad day, get an API key for SayGm and try a smaller, monitored catalog instead, same drop-in OpenAI-compatible setup, fewer unknowns to chase.

About SayGM

SayGm is a drop-in inference gateway for teams who don't want to just take a company's word that their prompts are private. Every request runs inside a hardware-verified confidential environment - not even SayGm can see what's inside it. That's not a policy, it's provable. Swap in your existing OpenAI, Anthropic, or Gemini code and you're covered in minutes, at transparent, published rates with no hidden markup.

Say gm to AI at saygm.com.

Website | Twitter | Discord | Blog | Medium | Docs

  • Inference
  • OpenRouter
BS

Brittany SealesMarketing

Saying gm to marketing (and AI)

X ↗