You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Upstream request failed: [server_error] Upstream response was not valid JSON #40194
Upstream request failed: [server_error] Upstream response was not valid JSON
Forbidden: {"model":"mimo-v2.5-free"}
It was the last couple of days, before that everything was always fine. I tried turning the VPN on and off, reinstalling, but nothing worked. On other free models, everything is the same, only Deepseek model is working
Plugins
OpenCode version
v1.18.11
Steps to reproduce
Select model
Submit the request
Get error
Screenshot and/or share link
No response
Operating System
Windows 11
Terminal
Windows Terminal or Opencode IDE
Reacted by Eyefinitys, i-kogda-nibud-nas-ne-budet, orionp13 and Luminous.X
OpenCode Go rejected your API key, so the model can't be reached. Update it in Settings → Providers, or run hermes setup in a terminal.
Provider said: HTTP 403: Upstream request failed: [server_error] Upstream response was not valid JSON
This turn did not complete. Some actions may already have run; verify their effects before resending.
I have the same issue i code with hermes agent and opencode go
{"type":"provider.auth","message":"Upstream request failed: [server_error] Upstream response was not valid JSON","status":403}
Where the text comes from: it is not in any client bundle (checked the 2.0.9/2.0.12/2.0.14 opencode-cli.exe, the desktop app.asar and OpenCode.exe). The client copies error.message from the HTTP response body, so the text is the relay's — consistent with the pointer at packages/console/app/src/routes/zen/util/handler.ts in the other thread.
Why the turn dies instead of retrying: the 403 makes the provider layer classify the error as reason tag Authentication → provider.auth, and the retry predicate treats Authentication as non-retryable. In the 2.0.14 bundle the predicate reads x-should-retry first, then switches on the reason:
So a body that self-identifies as server_error is never consulted once the status is 403. The message-pattern retryable list (which does match server_error) is not reached on this path.
Measured impact (one install): 22 stored failures across 12 sessions, 2026-09-20 → 09-23. Failed steps completed in 0.9–7.5 s (median ~1.9 s) — no retry chain. Fresh subagent sessions failed on their very first call, which argues against session-sticky routing being the whole story; failures cluster in short windows (two reviewer attempts two minutes apart both failed) and the same requests succeed minutes later.
The retry machinery itself is fine: stamping x-should-retry: true on exactly this 403 class makes the turn survive. Verified on a standalone 2.0.14 server with a local fault injection: inject the raw relay 403 → client retries seconds later → turn completes (exit 0). So the fix is the classification, not the retry loop.
Suggested direction: when a 403's structured body says server_error / upstream_unavailable, treat it as transient (retryable) rather than Authentication. The discriminator has to be the body, not the status: this endpoint also answers genuine request-shape errors as [invalid_request_error] (e.g. the reasoning_content replay rule), and those must keep failing fast — retrying them would only burn the budget. Same conclusion another client reached for this relay: NousResearch/hermes-agent#117869.
Happy to test a build or open a PR with a focused test if useful.
One more measurement for whoever implements the client-side fix — the retry budget, not just the classification, decides whether a sustained relay outage kills the turn.
Timeline from a subagent turn on 2.0.14 (2026-09-23), with a local guard that stamped x-should-retry: true on exactly this 403 class:
09:12:46.978 → 09:14:22.787: eleven consecutive retries roughly 3–12 s apart (the client's 2 s → 10 s schedule with jitter), each answered by another 403, then the budget ran out and the turn failed. So the header hint does make the client retry, but ~10 attempts × the fixed 2–10 s backoff is only about 100 s of tolerance — a longer outage still fails the turn.
What fixed it locally: re-frame the same 403 body as 502 plus retry-after-ms. In the 2.0.14 bundle the classifier maps status >= 500 to ProviderInternal, which is retryable and honours retry-after-ms (15-minute cap), so the wait can escalate per attempt (3/10/20/40/60 s ≈ 7 minutes of coverage) and the error is reported as provider.internal instead of the misleading provider.auth. Measured on a standalone 2.0.14 server with injected blips: four consecutive 403s → waits 3 s, 10 s, 20 s, 40 s on one chain → turn completed (exit 0).
One detail worth knowing if anyone takes this route: the retried request body grows as the failed attempt joins the history (133 KB → 152 KB → 161 KB in that capture), so the retry chain has to be keyed by the session, not by the payload.
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.
Activity
github-actions commentedon Aug 2, 2026
This issue might be a duplicate of existing issues. Please check:
If your issue is the same, please add a reaction or comment there instead of opening a new report.
CasperOng commentedon Sep 13, 2026
Same issue, Luna
orionp13 commentedon Sep 21, 2026
I have the same issue i code with hermes agent and opencode go
I use Deepseek V4.1 Flash
aaurelions commentedon Sep 22, 2026
It seems to me that
opencodev1 continued running after the error, butopencodev2 terminates the turn.4Liberty commentedon Sep 23, 2026
Confirming this on v2 with a measured client-side mechanism, in case it helps pin the fix.
Environment: OpenCode Desktop 2.0.9 → 2.0.14 (bundled CLI), Windows; provider
opencode-go, modeldeepseek-v4.1-flash.Stored error part:
{"type":"provider.auth","message":"Upstream request failed: [server_error] Upstream response was not valid JSON","status":403}Where the text comes from: it is not in any client bundle (checked the 2.0.9/2.0.12/2.0.14
opencode-cli.exe, the desktopapp.asarandOpenCode.exe). The client copieserror.messagefrom the HTTP response body, so the text is the relay's — consistent with the pointer atpackages/console/app/src/routes/zen/util/handler.tsin the other thread.Why the turn dies instead of retrying: the 403 makes the provider layer classify the error as reason tag
Authentication→provider.auth, and the retry predicate treatsAuthenticationas non-retryable. In the 2.0.14 bundle the predicate readsx-should-retryfirst, then switches on the reason:So a body that self-identifies as
server_erroris never consulted once the status is 403. The message-pattern retryable list (which does matchserver_error) is not reached on this path.Measured impact (one install): 22 stored failures across 12 sessions, 2026-09-20 → 09-23. Failed steps completed in 0.9–7.5 s (median ~1.9 s) — no retry chain. Fresh subagent sessions failed on their very first call, which argues against session-sticky routing being the whole story; failures cluster in short windows (two reviewer attempts two minutes apart both failed) and the same requests succeed minutes later.
The retry machinery itself is fine: stamping
x-should-retry: trueon exactly this 403 class makes the turn survive. Verified on a standalone 2.0.14 server with a local fault injection: inject the raw relay 403 → client retries seconds later → turn completes (exit 0). So the fix is the classification, not the retry loop.Suggested direction: when a 403's structured body says
server_error/upstream_unavailable, treat it as transient (retryable) rather thanAuthentication. The discriminator has to be the body, not the status: this endpoint also answers genuine request-shape errors as[invalid_request_error](e.g. thereasoning_contentreplay rule), and those must keep failing fast — retrying them would only burn the budget. Same conclusion another client reached for this relay: NousResearch/hermes-agent#117869.Happy to test a build or open a PR with a focused test if useful.
4Liberty commentedon Sep 23, 2026
One more measurement for whoever implements the client-side fix — the retry budget, not just the classification, decides whether a sustained relay outage kills the turn.
Timeline from a subagent turn on 2.0.14 (2026-09-23), with a local guard that stamped
x-should-retry: trueon exactly this 403 class:09:12:46.978→09:14:22.787: eleven consecutive retries roughly 3–12 s apart (the client's 2 s → 10 s schedule with jitter), each answered by another 403, then the budget ran out and the turn failed. So the header hint does make the client retry, but ~10 attempts × the fixed 2–10 s backoff is only about 100 s of tolerance — a longer outage still fails the turn.What fixed it locally: re-frame the same 403 body as 502 plus
retry-after-ms. In the 2.0.14 bundle the classifier mapsstatus >= 500toProviderInternal, which is retryable and honoursretry-after-ms(15-minute cap), so the wait can escalate per attempt (3/10/20/40/60 s ≈ 7 minutes of coverage) and the error is reported asprovider.internalinstead of the misleadingprovider.auth. Measured on a standalone 2.0.14 server with injected blips: four consecutive 403s → waits 3 s, 10 s, 20 s, 40 s on one chain → turn completed (exit 0).One detail worth knowing if anyone takes this route: the retried request body grows as the failed attempt joins the history (133 KB → 152 KB → 161 KB in that capture), so the retry chain has to be keyed by the session, not by the payload.
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊