Repository navigation
Description
Summary
When an OpenCode Go account exceeds its weekly model usage limit, requests fail with a misleading error: AI.Error.Authentication: Error from provider (Console Go): Upstream request failed: [server_error] Upstream response was not valid JSON. The real, actionable message (Weekly usage limit reached… enable usage from your available balance…) only appears in the server log, and the failure is classified as an authentication/JSON error instead of a quota/rate-limit error. Affected sessions look broken and the actual cause is hard to find.
Environment
- opencode version: 2.0.11 (OpenCode Desktop; bundled CLI reports
opencode v2.0.11). The separately installed npm CLI is V11.18.18. - OS: Windows 11 (NT 10.0.26200)
- Terminal: OpenCode Desktop app on Windows (no TUI)
- Shell: cmd.exe / PowerShell
- Install/channel: Desktop release (
ai.opencode.desktop), bundled CLI 2.0.11 - Active plugins: a local
gates.tsplugin file exists in the global configplugins/directory; unrelated to this issue. opencode service status:http://127.0.0.1:49374
Reproduction
- Use a provider account (OpenCode Go) whose weekly usage limit for a model is exhausted.
- Send a prompt to any session using that provider/model (e.g.
opencode-go/<model>#max). - The session fails with
AI.Error.Authentication: Error from provider (Console Go): Upstream request failed: [server_error] Upstream response was not valid JSON. - In
~/.local/share/opencode/log/opencode.log, the same time window shows the real cause:AI.Error: Weekly usage limit reached. Resets in 1hr 13min. To continue using this model now, enable usage from your available balance: https://opencode.ai/....
Expected Behavior
The client should surface the provider's actual message (weekly usage limit / quota exhausted) and classify it as a quota or rate-limit error, not as an authentication failure or invalid JSON.
Actual Behavior
AI.Error: Error from provider (Console Go): Upstream request failed: [server_error] Upstream response was not valid JSON
[cause]: AI.Error.Authentication: Error from provider (Console Go): Upstream request failed: [server_error] Upstream response was not valid JSON
The quota message is only visible in the log. Around the same window the log also shows: WARN failed to load OpenCode provider config cause="HttpClientError: StatusCode: non 2xx status code (401 GET https://opencode.ai/console/api/v2/config)".
Additional Context
- Frequency: intermittent while the limit is active (some requests succeed, most fail), across multiple sessions.
- Impact: the UI shows an auth/parse error; users cannot tell the account is out of quota and retries look like random flakiness.
- Workaround: switch to another credential/account or provider, enable balance usage, or wait for the weekly reset.
- Likely cause: the provider's quota response body is not JSON and the client's error mapping wraps it as
AI.Error.Authentication. - Sanitized log lines (credentials and session ids removed):
level=ERROR message="Failed to drain Session" cause="AI.Error: Error from provider (Console Go): Upstream request failed: [server_error] Upstream response was not valid JSON"level=ERROR message="Failed to drain Session" cause="AI.Error: Weekly usage limit reached. Resets in 1hr 13min. To continue using this model now, enable usage from your available balance: https://opencode.ai/..."
Activity
jinhuang712 commentedon Sep 21, 2026
Adding a data point with the same message but a different signature (403
provider.auth, transient recovery), in case it is a separate root cause.Environment
v2.0.12, macOS (Darwin 25.5.0, arm64), zshopencode-go(Go subscription), modeldeepseek-v4.1-flash(observed on both#maxand default variants)What I saw
Five failures across four sessions between
2026-09-21 12:13and17:44UTC. The persisted assistant error is identical each time:{"type":"provider.auth","message":"Error from provider (Console Go): Upstream request failed: [server_error] Upstream response was not valid JSON","status":403}The outer error comes from
SessionRunner.drainand wrapsAI.Error.Authentication, so the turn dies immediately. Because it is classified asprovider.auth(non-retryable), no retry is attempted even though the upstream body carriesserver_error.Findings
Upstream request failed: [server_error] Upstream response was not valid JSONdoes not exist anywhere in the client repo. It is produced upstream of the gateway; the gateway only adds theError from provider (Console Go):prefix (packages/console/app/src/routes/zen/util/handler.ts:337), which means the gateway reached an upstream that answered403with a JSON error body.x-opencode-session. Without it the gateway answers400 MissingSessionID(Request is missing x-opencode-session and cannot be routed efficiently). Routing is session-derived, so a bad upstream can stay sticky to specific sessions.2026-09-22(non-stream, stream, withtools, 12 different session shards, and a ~67k-char prompt with"reasoning_effort":"max") returnedHTTP 200. So on my side this looks like a transient upstream window rather than a persistent quota state. Responses show"cost":"0".server_error, which the current retry patterns match (packages/opencode/src/session/retry.ts:36). Ifv2.0.12reclassifies this toprovider.authbefore the retry decision is evaluated, that would explain the missing retry. Worth checking whether the retry decision runs before or after provider-auth classification.Not claiming this is the quota-masking case described above — the
403+provider.auth+ recovery-without-a-quota-reset looks different — but recording it here rather than opening a duplicate.4Liberty commentedon Sep 23, 2026
Answering the open question in @jinhuang712's data point — whether the retry decision runs before or after provider-auth classification: classification runs first, and it wins.
Measured on 2.0.9–2.0.14: the 403 becomes reason tag
Authentication, the stored part isprovider.auth, and the retry predicate returns false forAuthentication(after checkingx-should-retryfirst). The retryable message patterns, which do matchserver_error, are never consulted on this path. A guard that stampsx-should-retry: trueon exactly this class makes the client retry and the turn completes — so the retry loop is fine.Full mechanism plus a 22-failure measurement over three days is in #40194.
opencodejr commentedon Oct 28, 2026
Thanks for the detailed report and the log lines. We couldn't reproduce this here: it needs an OpenCode Go account whose weekly limit is used up, and we don't have one in this environment.
From the code: OpenCode already treats Go usage-limit responses as quota errors and shows the provider's message, as long as the response comes back as a quota or rate-limit error (402, or 429 with a usage-limit code or message). That's why the
Weekly usage limit reached…error appears for some of your requests. The failing requests look different: theAI.Error.Authenticationlabel means the Go gateway itself answered with a 401/403 whose body only saidUpstream response was not valid JSON, so the app had nothing about the quota to show. The 401 on the console config request in the same window points the same way.So this most likely needs fixing in how the OpenCode Go service responds when the limit is reached, and that needs a maintainer with access to it. If you can catch the raw HTTP status and body of one failing request, adding it here would help.