anomalyco / anomalyco/opencode
Zen 429 FreeUsageLimitError is masked as "Unexpected server error" (TypeError in SystemPrompt.environment)
@MrMushrooooom is already working on this.
Since Sep 14, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- Avg merge
- 7h 2m
- Merged PRs (30d)
- 384
Description
Description
When the OpenCode Zen free tier is rate-limited, the provider returns a clear, well-formed
429 FreeUsageLimitError. OpenCode discards it and reports an internal TypeError instead,
so the user sees only:
Failed to send prompt
Unexpected server error. Check server logs for details.
This is misleading in two ways:
- The actionable provider message ("Rate limit exceeded") never reaches the user.
- The
refshown in the UI does not exist in the log, so "check server logs" is unactionable.
Environment
- OpenCode 1.18.30 (Homebrew, macOS 26 "Tahoe", Apple Silicon)
- Provider:
opencode(Zen), free models — e.g.muse-spark-1.3-contributor-free - No Zen credential configured (the free tier needs none —
opencode auth listreports 0 credentials)
Steps to reproduce
- Use any Zen free model (
opencode/mimo-v2.5-free,opencode/muse-spark-1.3-contributor-free, …). - Send any prompt.
- Observe
Unexpected server errorimmediately, with aref.
All free models fail identically, which is the first clue that it is the shared free-tier
limiter rather than a model or config problem.
Evidence
1. The provider says exactly what is wrong. Calling the endpoint directly with the same
header the client sends (x-opencode-session):
$ curl -s -w " http=%{http_code}" https://opencode.ai/zen/v1/chat/completions \
-H 'content-type: application/json' \
-H 'x-opencode-session: <session-id>' \
-d '{"model":"mimo-v2.5-free","messages":[{"role":"user","content":"hi"}],"max_tokens":5}'
http=429 {"type":"error","error":{"type":"FreeUsageLimitError",
"message":"Error from provider (Console): Rate limit exceeded. Please try again later."}}
(Without that header the same endpoint returns
400 {"type":"error","error":{"type":"MissingSessionID","message":"Error from provider (Console): OpenCode's free tier can only be used in OpenCode"}},
so the free tier is gated on the client session, not on an API key.)
2. The log records a client-side TypeError, not the provider error. From
~/.local/share/opencode/log/opencode.log:
level=ERROR message=failed ref=err_a184f806
error="TypeError: undefined is not an object (evaluating 'a.name')"
at resolve (/$bunfs/root/chunk-36bwgd4p.js:2:1659)
...
at SystemPrompt.environment (/$bunfs/root/chunk-y88jw4qv.js:50:13096)
at SessionPrompt.run ...
The stack points into SystemPrompt.environment. On dev, that function sorts project
references as references.toSorted((a, b) => a.name.localeCompare(b.name))
(packages/opencode/src/session/system.ts), which throws exactly this TypeError if any
entry has an undefined name. Whether that is the precise trigger here, or a second
undefended .name access on the same path, is for you to confirm — but the crash happens
while building the system prompt, before any provider error can be surfaced.
3. The UI ref is not in the log. The TUI reported ref: err_db8fa078; grepping the log
for that string returns 0 matches (the log's own ref for the same failure was
err_a184f806). The two refs are generated at different layers and never reconciled.
Ruled out
The failure is independent of local configuration. It reproduces identically with:
- an empty config (only
$schema) - the MCP block removed
- the plugin removed from config and its cached package removed from
~/.cache/opencode/packages/ - the skills directory moved aside
- a fresh state directory (no DB, no sessions)
- a different free model
- a clean
brew reinstall opencode
Expected
- Surface the provider's status and message — e.g.
429 FreeUsageLimitError: Rate limit exceeded. Please try again later.— rather than an internalTypeError. - Do not collapse provider errors into
UnknownError/"Unexpected server error". - Make the
refin the UI resolvable in the log (same ref, or print the log path with it). - Since the free tier is quota-limited, a clear "free tier rate limit reached, resets at X / add credits" message would prevent a lot of misdiagnosis.
Related issues
Same symptom, no root cause identified: #36826, #29748, #48792, #41944.
Zen free-tier limiting: #43786, #45132, #33318, #33495, #32971.
Error classification: #47685.
Impact
This is a debugging trap: the opaque error sends users hunting for local causes (plugins,
MCP config, credentials) when nothing local is broken. It cost me an hour of bisecting a
config that was never the problem.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.