Repository navigation
Description
Description
OpenCode free tier models (mimo-v2.5-free, muse-spark-1.2-contributor-free) started returning 403 FreeTierError when accessed through 9router proxy. This started approximately 15 minutes ago (Sep 16, 2026 ~20:55 UTC-3). The models were working fine for weeks before this.
Error Log
20:55:50 🟢 ▶ POST oc/mimo-v2.5-free → opencode/mimo-v2.5-free · FMT: openai→openai · STREAM · 2 MSG · 38 TOOL · ACC:Public
20:55:50 ℹ️ PROXY OPENCODE | mimo-v2.5-free | conn=Public | pool=*** | vercel-relay=https://elysium-hw3a89h6n-elysium13.vercel.app
20:55:50 🔵 ▶ POST oc/mimo-v2.5-free → opencode/mimo-v2.5-free · FMT: openai→openai · JSON · 2 MSG · ACC:Public
20:55:51 🔵 ✗ ERROR 403 · opencode/mimo-v2.5-free · 779ms URL: https://opencode.ai/zen/v1/chat/completions 403: {"type":"error","error":{"type":"FreeTierError","message":"Error from provider (Console): OpenCode's free tier can only be used from within OpenCode"}}
20:55:53 🟢 ✗ ERROR 403 · opencode/mimo-v2.5-free · 2196ms URL: https://opencode.ai/zen/v1/chat/completions 403: {"type":"error","error":{"type":"FreeTierError","message":"Error from provider (Console): OpenCode's free tier can only be used from within OpenCode"}}
20:55:53 🟢 ▶ POST oc/muse-spark-1.2-contributor-free → opencode/muse-spark-1.2-contributor-free · FMT: openai→openai-responses · STREAM · 1 MSG · 38 TOOL · ACC:Public
20:55:53 🟢 ✗ ERROR 403 · opencode/muse-spark-1.2-contributor-free · 420ms URL: https://opencode.ai/zen/v1/responses 403: {"type":"error","error":{"type":"FreeTierError","message":"Error from provider (Console): OpenCode's free tier can only be used from within OpenCode"}}
Environment
- 9router version: latest
- Models affected:
oc/mimo-v2.5-free,oc/muse-spark-1.2-contributor-free - Provider:
opencode(viaopencode.ai/zen/v1) - Connection: Public
Additional Context
- These models were working fine through 9router for weeks before this error started.
- The error suggests OpenCode added server-side validation to ensure free tier models can only be accessed from the official OpenCode client.
- This seems to be a new restriction deployed by OpenCode in the last ~15 minutes.
- Other users may be affected by this change.
Expected Behavior
Free tier models should continue to work through the 9router proxy as they did before.
Actual Behavior
All free tier models return 403 with FreeTierError: OpenCode's free tier can only be used from within OpenCode.
Activity
arwinwijaya commentedon Sep 17, 2026
i have same issue
anojndr commentedon Sep 17, 2026
Identified the root cause of this error:
OpenCode upstream deployed two server-side validation checks on free tier endpoints (
/zen/v1/chat/completionsand/zen/v1/responses) when usingAuthorization: Bearer public:User-Agent: opencode/<version>with version >=1.17.0. Bareopencodeor third-party client user agents trigger403 FreeTierError(and versions <1.17.0receive426 Upgrade Required). 9router was defaulting to bareUser-Agent: opencode.x-opencode-session): Upstream enforces OpenCode's canonical descending identifier format:ses_+ 12 hex timestamp characters + 14 Base62 characters (/^ses_[0-9a-f]{12}[0-9A-Za-z]{14}$/, 30 characters total). Missing headers or raw UUID formats trigger403 FreeTierError.Fix submitted in PR #4105:
User-Agenttoopencode/1.18.31and validates downstream client versions.OpenCodeExecutorfor safe concurrent request handling.fix(opencode): resolve 403 FreeTierError with canonical session forma…
[feat/combo-health-fallback] fix(opencode): resolve 403 FreeTierError…
LustHK commentedon Sep 17, 2026
Wow! The people here are really fast.
anojndr commentedon Sep 17, 2026
Update — my earlier comment here (PR #4105) was an incomplete fix: it covered only 2 of the 4 gates upstream enforces, which is why the 403 came back within hours.
Live bisection with genuine
opencode/1.18.31+ canonicalses_held constant found the two missing gates Zen enforces withBearer public:{bash, glob, grep, read}quartet → 200 on both/chat/completionsand/responses. Extras allowed, fake names fail. Plain chat callers send no tools, so every such request 403s.stream:false→ 403 on both endpoints even when everything else is valid.New PR #4132 completes the fingerprint: forces
stream:trueupstream (non-stream clients still get JSON via the existing forced-SSE path) and merges the missing quartet declarations, preserving caller tools verbatim. Verified live post-fix:mimo-v2.5-free,ling-3.0-flash-fin-free,nemotron-3.5/3-ultra-free,big-pickle,muse-spark-1.2/1.3-contributor-freeall 200, including with non-stream flag. 65 opencode unit tests pass, baselines byte-equal.fix(opencode): complete free-tier client fingerprint to stop recurrin…
release(v0.9.64): the versioned gate — Zen's free tier answers again ⚿
fix(opencode): complete free-tier client fingerprint to stop recurrin…
nonamcabibaranani-design commentedon Sep 18, 2026
+1, hitting the exact same via 9router proxy. Hope this gets a fix soon!
nonamcabibaranani-design commentedon Sep 18, 2026
+1, hitting the exact same FreeTierError via 9router proxy.
release(v0.9.64): the versioned gate — Zen's free tier answers again ⚿
fix(opencode): resolve 403 FreeTierError with canonical session forma…
fix(opencode): complete free-tier client fingerprint to stop recurrin…
fix(opencode): complete free-tier client fingerprint to stop recurrin…
fix(opencode): resolve 403 FreeTierError with canonical session forma…
fix(opencode): complete free-tier client fingerprint to stop recurrin…
fix(opencode): complete free-tier client fingerprint to stop recurrin…
fix(opencode): complete free-tier client fingerprint to stop recurrin…
fix(opencode): encode inverted timestamp in translated session IDs (d…
fix(opencode): encode inverted timestamp in translated session IDs (#…
fix(opencode): encode inverted timestamp in translated session IDs (d…
Merge decolua/master v0.5.104 into fork (#15)
feat(ui): warm-workbench redesign foundation, live Providers workbenc…
jauharymanshura9-max commentedon Oct 19, 2026
Additional finding: IP-reputation gate separate from the fingerprint gate
We've been running 9router with OpenCode free tier through a de-duplicated WARP IP pool (3 distinct egress addresses) and logging every request. Our data shows there are two separate 403 gates, not one:
readtool, wrong User-Agent, wrong session format → "can only be used from within OpenCode"Quantitative evidence (1000 requests, ~8 hours):
Model-specific sensitivity to IP abuse:
Workaround that worked for us: Route 9router's OpenCode provider through Cloudflare WARP with multiple distinct egress IPs. De-duplicate the pool (WARP assigns from a small regional pool — nodes collide by default). Automatic failover on 403/429 across different IPs.
Key insight for 9router: The fingerprint fix (this issue) solves gate #1, but gate #2 (IP abuse) still causes failures for users on flagged IP ranges. Even WARP IPs get flagged over time — a pool of 5+ distinct IPs with automatic rotation provides better sustained reliability.
fix(opencode): encode inverted timestamp in translated session IDs (d…
fix(opencode): encode inverted timestamp in translated session IDs (d…