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
Top-level permission: {"read": "deny"} makes every headless opencode run fail with a misleading free-tier 403 #55653
opencode 1.19.0, macOS (darwin). The repro is a single config key.
Supplying an inline config merge that denies top-level read causes every headless opencode run to fail:
{"permission":{"read":"deny"}}
$ OPENCODE_CONFIG_CONTENT='{"permission":{"read":"deny"}}' \
opencode run "Reply with exactly: PROBE_OK" --model opencode/space-bunny-free --format json
{"type":"error", ... "error":{"name":"APIError","data":{
"message":"OpenCode's free tier can only be used from within OpenCode. Download it at https://opencode.ai and keep building.",
"statusCode":403, "isRetryable":false, ...}}}
Order-independent — interleaved A/B/C over 3 rounds, identical results each round. Not rate limiting.
Narrow — sweeping all eleven documented permission keys individually, read is the only one that triggers it. bash, edit, glob, grep, list, task, webfetch, websearch, lsp, skill all pass.
Nesting matters — the identical denial scoped inside an agent definition works.
Why this reads as a bug rather than a tier gate
All six probes above ran on the same account, same free tier, same model. Four succeeded. A billing check fails consistently; this one flips on config shape alone.
The practical cost is that the error text is misleading: it points users at upgrading to a paid plan for behaviour that payment does not change. If this is deliberate free-tier policy, the boundary seems arbitrary — read: "deny" behaves differently from read: "ask", which is not a distinction a user would guess at. Either way the error message seems worth revising.
Workaround
Scope the denial to an agent instead of top level:
Thanks for the very thorough matrix! I think this is a duplicate of #51241. The free-tier check runs on the server, not in OpenCode. It looks at which tools are listed in the model request. A top-level "read": "deny" takes the read tool out of that list, so the server rejects the request as if it came from outside OpenCode. ask keeps the tool in the list, which is why it works. A deny inside a subagent definition doesn't change the main agent's request.
Possible duplicates and related issues, ordered by likelihood:
Your finding that the error message points users the wrong way, and your agent-scoped workaround, would be useful on #50627.
Also, 1.19.0 is OpenCode v1, which only gets critical fixes now. Upgrading to v2 is recommended (opencode upgrade --major), though this free-tier check also affects v2 for now.
The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
Follow-up from a longer investigation — the minimal repro is now exact, and my first report understated it.
Correction
The first matrix was misleading. Several of those rows defined the agent in config but never selected it with --agent, so the permission block was never in effect. Selecting the agent changes things.
Real trigger: read only, regardless of nesting or selection
--standalone makes no difference. So: denying read is the trigger. Denying every other tool — including edit and bash — works fine. It is not about nesting, not about top-level vs agent-scoped, and not about subagent mode.
This is a strange boundary because it is so arbitrary: a user denying edit gets what they asked for, and a user denying read gets a billing error telling them to upgrade.
Impact on tool-restriction use cases
This isn't cosmetic for headless/automated callers. Any workflow that restricts an agent's tools has to leave read enabled on the free tier, which is the one capability most likely to leak context into output. Scenarios that restrict everything exceptread work correctly, so it looks fine until you try to close the last hole.
Still worth answering
Is this intended? If read denial is restricted on the free tier, the error should say so — the current message sends people to buy credits for behaviour that payment doesn't change.
Does it reproduce on a paid tier / own-key provider? If not, it should at least say which tier it applies to.
Filed from an open-source project (automemory) where a blind summarisation agent depends on this; happy to provide a repro script.
Thanks for the correction and the clean matrix. The corrected trigger, where denying read fails and denying everything else works, still matches #51241 exactly. That issue's title is "Free models fail when shell or read permissions are denied", and it has confirmations on 1.18.x too. So I still think this is a duplicate of #51241, and #50627 is the broader issue for the same check. Your new data is still useful there: on your setup bash: "deny" passes, while several reporters in #50627 saw it fail. That suggests the set of tools the gateway expects has changed over time.
On your questions:
Is this intended? Nothing from the team says it is. What the earlier threads found is that the free-tier check runs on the OpenCode Zen gateway, not in the app. It looks at which tools are listed in the model request. A deny (or tools.read: false) takes read out of that list, so the gateway treats the request as if it didn't come from OpenCode. That's also why ask works: the tool stays in the list. I agree the error message is misleading for this case. That's worth adding to [BUG] Free models fail when shell or read permissions are denied #51241.
Paid tier or your own key? This message comes from the Zen free-tier check, so requests to providers you've configured with your own API key don't go through it. I can't confirm how paid Zen models behave. A data point from you on [BUG] Free models fail when shell or read permissions are denied #51241 would help.
For your read-restricted summariser, two things to try in the meantime:
Run that agent on a provider with your own key, or on a non-free model.
Also, 1.19.0 is OpenCode v1, which only gets critical fixes now. The same gateway check affects v2 as well.
Unless the new details show a different problem, this issue will still be closed as a duplicate of #51241. Please add your matrix and the automemory use case there, so it stays with the other reports.
Thanks — the mechanism explains my data cleanly, and #51241 / #50627 are indeed the same thing. Posting the matrix to #50627 as suggested.
One correction to the workaround, since it would mislead anyone headless: agent-scoping the deny does not survive --agent.
A deny inside a subagent definition doesn't change the main agent's request.
True for a subagent spawned within a session. But opencode run --agent X makes X the session's agent, so X's tool list is the one sent:
Config
selected via --agent?
result
agent defined with permission: {read: "deny"}
no
OK
same agent, same config
yes
403 (3/3)
So for a headless caller there's no agent-scoped escape — if you can't leave read in the tools list, you can't have full blindness on the free tier. That also means the --disallowed-tools story doesn't have a config-only equivalent the way I assumed in the original report.
Two data points that may narrow it:
bash: "deny" does NOT trigger it on 1.19.0 (2/2 OK), alongside read: "allow" and read: "ask" both OK. [BUG] Free models fail when shell or read permissions are denied #51241 lists reador shell; I could not reproduce a shell trigger via the bash permission key. Possibly a different key, or version-specific.
Agreed on the error message: it points at billing for behaviour that payment doesn't change, and "download OpenCode" is actively wrong when you're already running it. That seemed worth a report on its own.
Thanks for confirming, and for the correction. You're right: my note about subagent definitions only holds for subagents started within a session. With opencode run --agent X, X is the session's agent, so its read: "deny" removes read from the request and the 403 comes back. For headless use, then, the only workarounds are the ones that keep read in the request: a narrow read allow pattern (not yet checked on 1.19.0), or a provider/model that doesn't go through the free-tier check.
Closing this as a duplicate of #51241, as discussed. That issue tracks the free-tier 403 that happens when read is denied or disabled, and #50627 covers the same server-side check more broadly. Thanks for the detailed matrices and for adding them to #50627. The finding that --agent puts the agent's deny back into effect, and your notes on the misleading error message, will help whoever works on the fix. If you see a case that doesn't fit #51241, please open a new issue with the details.
Activity
opencode-agent commentedon Oct 15, 2026
Thanks for the very thorough matrix! I think this is a duplicate of #51241. The free-tier check runs on the server, not in OpenCode. It looks at which tools are listed in the model request. A top-level
"read": "deny"takes thereadtool out of that list, so the server rejects the request as if it came from outside OpenCode.askkeeps the tool in the list, which is why it works. A deny inside a subagent definition doesn't change the main agent's request.Possible duplicates and related issues, ordered by likelihood:
shellorreadpermissions are denied #51241: free models fail whenreadorshellis denied, with the same error (open)tools.read: falsecaused the same error on 1.18.x (closed as a v1 issue)Your finding that the error message points users the wrong way, and your agent-scoped workaround, would be useful on #50627.
Also, 1.19.0 is OpenCode v1, which only gets critical fixes now. Upgrading to v2 is recommended (
opencode upgrade --major), though this free-tier check also affects v2 for now.The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
hellovalerie commentedon Oct 15, 2026
Follow-up from a longer investigation — the minimal repro is now exact, and my first report understated it.
Correction
The first matrix was misleading. Several of those rows defined the agent in config but never selected it with
--agent, so the permission block was never in effect. Selecting the agent changes things.Real trigger:
readonly, regardless of nesting or selection--agentpermission: {read: "deny"}permission: {read: "deny"}permission: {edit,glob,grep,list,bash,task,webfetch,websearch,lsp,skill: "deny"}(everything except read)permission: {bash: "deny"}tools: {bash:false, write:false, edit:false}tools: {read:false, ...everything}--standalonemakes no difference. So: denyingreadis the trigger. Denying every other tool — includingeditandbash— works fine. It is not about nesting, not about top-level vs agent-scoped, and not about subagent mode.This is a strange boundary because it is so arbitrary: a user denying
editgets what they asked for, and a user denyingreadgets a billing error telling them to upgrade.Impact on tool-restriction use cases
This isn't cosmetic for headless/automated callers. Any workflow that restricts an agent's tools has to leave
readenabled on the free tier, which is the one capability most likely to leak context into output. Scenarios that restrict everything exceptreadwork correctly, so it looks fine until you try to close the last hole.Still worth answering
readdenial is restricted on the free tier, the error should say so — the current message sends people to buy credits for behaviour that payment doesn't change.Filed from an open-source project (automemory) where a blind summarisation agent depends on this; happy to provide a repro script.
opencode-agent commentedon Oct 15, 2026
Thanks for the correction and the clean matrix. The corrected trigger, where denying
readfails and denying everything else works, still matches #51241 exactly. That issue's title is "Free models fail whenshellorreadpermissions are denied", and it has confirmations on 1.18.x too. So I still think this is a duplicate of #51241, and #50627 is the broader issue for the same check. Your new data is still useful there: on your setupbash: "deny"passes, while several reporters in #50627 saw it fail. That suggests the set of tools the gateway expects has changed over time.On your questions:
deny(ortools.read: false) takesreadout of that list, so the gateway treats the request as if it didn't come from OpenCode. That's also whyaskworks: the tool stays in the list. I agree the error message is misleading for this case. That's worth adding to [BUG] Free models fail whenshellorreadpermissions are denied #51241.shellorreadpermissions are denied #51241 would help.For your read-restricted summariser, two things to try in the meantime:
readin the request but make it useless. Use a pattern rule that denies everything except one harmless path, e.g."read": { "*": "deny", "some/nonexistent/path": "allow" }. In free models: subagent fails with "free tier can only be used from within OpenCode" when deny-first permissions leave the agent with no allowed actions #54882 a narrow allow rule kept the tool listed and the request passed. I haven't verified this exact form on 1.19.0, so please check it.Also, 1.19.0 is OpenCode v1, which only gets critical fixes now. The same gateway check affects v2 as well.
Unless the new details show a different problem, this issue will still be closed as a duplicate of #51241. Please add your matrix and the automemory use case there, so it stays with the other reports.
hellovalerie commentedon Oct 16, 2026
Thanks — the mechanism explains my data cleanly, and #51241 / #50627 are indeed the same thing. Posting the matrix to #50627 as suggested.
One correction to the workaround, since it would mislead anyone headless: agent-scoping the deny does not survive
--agent.True for a subagent spawned within a session. But
opencode run --agent Xmakes X the session's agent, so X's tool list is the one sent:--agent?permission: {read: "deny"}So for a headless caller there's no agent-scoped escape — if you can't leave
readin the tools list, you can't have full blindness on the free tier. That also means the--disallowed-toolsstory doesn't have a config-only equivalent the way I assumed in the original report.Two data points that may narrow it:
bash: "deny"does NOT trigger it on 1.19.0 (2/2 OK), alongsideread: "allow"andread: "ask"both OK. [BUG] Free models fail whenshellorreadpermissions are denied #51241 listsreadorshell; I could not reproduce ashelltrigger via thebashpermission key. Possibly a different key, or version-specific.tools: {read: false}reproduces it identically (2/2), matching tools.read = false in opencode.json makes all zen free-tier models fail with "free tier can only be used from within OpenCode" #51315 — which was closed as v1. Since this affects v2 as well, that closure may be worth revisiting.Agreed on the error message: it points at billing for behaviour that payment doesn't change, and "download OpenCode" is actively wrong when you're already running it. That seemed worth a report on its own.
Co-Authored-By: opencode/space-bunny-free noreply@opencode.ai
opencode-agent commentedon Oct 16, 2026
Thanks for confirming, and for the correction. You're right: my note about subagent definitions only holds for subagents started within a session. With
opencode run --agent X, X is the session's agent, so itsread: "deny"removesreadfrom the request and the 403 comes back. For headless use, then, the only workarounds are the ones that keepreadin the request: a narrowreadallow pattern (not yet checked on 1.19.0), or a provider/model that doesn't go through the free-tier check.On your two data points:
shellvsbash: [BUG] Free models fail whenshellorreadpermissions are denied #51241 was filed against v2.0.16, where the permission is calledshell. Your 1.19.0 test used v1'sbashkey, so it may not be testing the same rule. Either way, your result thatbash: "deny"passes is useful on policy: deny shell * on custom agent breaks free tier with "can only be used from within OpenCode" #50627, since reporters there saw it fail on earlier 1.18.x versions.shellorreadpermissions are denied #51241, so that's where it gets followed up. Whether to reopen tools.read = false in opencode.json makes all zen free-tier models fail with "free tier can only be used from within OpenCode" #51315 is up to the maintainers.Thanks also for raising the error message. Your matrix and the confusing "download OpenCode" wording are useful on #51241 and #50627.
As agreed, this issue will be closed as a duplicate of #51241.
opencode-agent commentedon Oct 16, 2026
Closing this as a duplicate of #51241, as discussed. That issue tracks the free-tier 403 that happens when
readis denied or disabled, and #50627 covers the same server-side check more broadly. Thanks for the detailed matrices and for adding them to #50627. The finding that--agentputs the agent's deny back into effect, and your notes on the misleading error message, will help whoever works on the fix. If you see a case that doesn't fit #51241, please open a new issue with the details.