Description
Title:
[Bug] OpenRouter upstream for z-ai/glm-5.3-flash returns reseller panel error as 200-OK assistant content (billed, no failover)
Summary
While using openrouter/z-ai/glm-5.3-flash in opencode, the model's "answer" was literally the raw error message of an upstream reseller panel:
Your quota is exhausted.
API key status: exceeded
Name: VIP.aaa
USDT balance: -9.110032 USDT
USDT spent: 140.900032 USDT
exp_date: 2026-11-03T04:07:25.259Z
This was NOT an HTTP error: the request completed normally (finish reason stop), the text was stored and displayed as the assistant message, and the request was billed as a normal completion. OpenRouter's provider failover never triggered because the response looked like a successful 200-OK.
Evidence
- opencode 1.18.34, provider
openrouter, model z-ai/glm-5.3-flash
- Session DB entry (2026-10-08 13:37 UTC): assistant message with
finish: "stop", tokens input 150,819 / output 58, cost $0.02265185
- My OpenRouter account is fine: key valid, no per-key limit, positive balance (verified via
GET /api/v1/key)
- Direct test call to
openrouter.ai/api/v1/chat/completions with the same key works normally (routed to GMICloud)
- The error text format (USDT balance, key name, exp_date) is a one-api/new-api style reseller panel — clearly neither OpenRouter nor Z.ai official
Root cause (assumed)
z-ai/glm-5.3-flash is served by ~30 upstream providers on OpenRouter. At least one of them appears to be a reseller whose own panel key ("VIP.aaa") ran out of USDT quota. Instead of returning an HTTP error (which would trigger OpenRouter failover), the panel returns the error text as a 200-OK completion, which OpenRouter passes through verbatim and bills.
Compounding problem: parroting
Once this text is in the conversation context, GLM-5.3-flash tends to echo it verbatim in subsequent turns — several assistant replies consisted solely of the error text. This makes it look like a persistent quota problem on the user's side, which it is not.
Related
Suggestions
- OpenRouter: consider scanning 200-OK completions for known panel-error patterns (or require upstreams to error properly) and fail over / not bill such responses.
- Users: check openrouter.ai/activity to identify the provider that served the request and pin/exclude it via provider routing.
- opencode: maybe worth flagging assistant messages that consist entirely of known upstream error patterns?
Happy to provide the generation ID from the activity page if needed.
Plugins
No response
OpenCode version
No response
Steps to reproduce
No response
Screenshot and/or share link
No response
Operating System
No response
Terminal
No response
Description
Title:
[Bug] OpenRouter upstream for z-ai/glm-5.3-flash returns reseller panel error as 200-OK assistant content (billed, no failover)
Summary
While using
openrouter/z-ai/glm-5.3-flashin opencode, the model's "answer" was literally the raw error message of an upstream reseller panel:This was NOT an HTTP error: the request completed normally (finish reason
stop), the text was stored and displayed as the assistant message, and the request was billed as a normal completion. OpenRouter's provider failover never triggered because the response looked like a successful 200-OK.Evidence
openrouter, modelz-ai/glm-5.3-flashfinish: "stop", tokens input 150,819 / output 58, cost$0.02265185GET /api/v1/key)openrouter.ai/api/v1/chat/completionswith the same key works normally (routed to GMICloud)Root cause (assumed)
z-ai/glm-5.3-flashis served by ~30 upstream providers on OpenRouter. At least one of them appears to be a reseller whose own panel key ("VIP.aaa") ran out of USDT quota. Instead of returning an HTTP error (which would trigger OpenRouter failover), the panel returns the error text as a 200-OK completion, which OpenRouter passes through verbatim and bills.Compounding problem: parroting
Once this text is in the conversation context, GLM-5.3-flash tends to echo it verbatim in subsequent turns — several assistant replies consisted solely of the error text. This makes it look like a persistent quota problem on the user's side, which it is not.
Related
Suggestions
Happy to provide the generation ID from the activity page if needed.
Plugins
No response
OpenCode version
No response
Steps to reproduce
No response
Screenshot and/or share link
No response
Operating System
No response
Terminal
No response