Repository navigation
Description
Description
Selecting any OpenCode Console (Zen) model in the TUI/CLI fails with the bare message:
Error: Workspace access denied
The message is the upstream HTTP body ({"type":"error","error":{"type":"permission_error","message":"Workspace access denied"}}).
Nothing in the client says that this is a server-side workspace/account restriction, so it reads like a local
permissions bug: users reinstall, re-login, rotate keys, and open account-support issues (see #58314, #58404, #57245,
#56703).
Every other provider keeps working from the same machine at the same time, which makes the failure look model-specific.
Environment
- opencode v2.1.4 (Linux), TUI and
opencode run - provider: OpenCode Console (
opencode), credential stored via/connect - model:
opencode/deepseek-v4.1-flash-free(also fails for paid Console models, e.g.opencode/deepseek-v4.1-flash) - control: a plain
@ai-sdk/openai-compatibleprovider with a direct vendor key works from the same session
Evidence
Client log (~/.local/share/opencode/log/opencode.log):
level=WARN message="failed to load OpenCode provider config"
cause="HttpClientError: StatusCode: non 2xx status code (403 GET https://opencode.ai/console/api/v2/config)"
level=ERROR message="Failed to drain Session"
cause="AI.Error: Workspace access denied ... [cause]: AI.Error.Authentication: Workspace access denied"
Same stored Console credential, replayed outside the client:
GET https://opencode.ai/console/api/v2/config
-> 403 {"_tag":"Forbidden"}
POST https://opencode.ai/inference/openai/v1/chat/completions (model: deepseek-v4.1-flash)
-> 403 {"type":"error","error":{"type":"permission_error","message":"Workspace access denied"}}
A second (expired) key on the same account answers 401 api_key_expired, so the two failures are distinguishable
server-side — only the workspace-denied one reaches the user unexplained.
Why it is unactionable today
In packages/core/src/plugin/provider/opencode.ts:
fetchConfig()handles401(SignedOutError) and a403whose body isSsoRequired. Any other 403 — including
Console's{"_tag":"Forbidden"}— falls through tofilterStatusOk, is logged as the generic
"failed to load OpenCode provider config" warning, and produces no connection status viaconnectionStatus().explain()only rewrites the inference response whenreportedis set. Withreported === undefinedthe raw
upstream body is left in place, so the TUI showsWorkspace access deniedand the CLI shows it as
AI.Error.Authentication.
That is the missing branch: a 403 that is definitely not SSO and not an expired key currently has no message.
Proposal
- Parse the
403 {"_tag":"Forbidden"}from/api/v2/configand apermission_errorbody from inference, and give
them a status like the existingneeds_authpath — e.g.status: "restricted"with the text:
"Your OpenCode Console workspace is restricted (HTTP 403). Check the workspace at
https://opencode.ai/console, or contact [email protected] if it stays restricted." - Keep the general fallback: for any Console 401/403 whose body is not recognised, append the Console URL and the
support address instead of passing the raw string through, so the failure is never a dead end. - Optional: treat the config-load 403 as a warning that names the workspace/connection (the
x-org-idheader is
only sent whenmetadata.orgIDexists, so an org-scoped key gives no context in the log either).
This mirrors what #51847 already did for the SSO case; the workspace-restriction case is the remaining one.
Related
- Paid OpenCode Go Workspace Access Denied – Multiple Support Requests Unanswered #58314 — paid OpenCode Go,
Workspace access deniedin CLI and 403 on direct API; maintainers: "a restriction on the
account itself" - Locked out of my OpenCode Go account/workspaces #58404, [Account/Workspace Issue] "Workspace access restricted" for sole Owner account #57245, Console: all workspaces restricted since Oct 17, no breach email received #56703 — "Workspace access restricted" across workspaces since 2026-10-17
- feat(core): tell users how to sign back in to OpenCode Console #51847 — existing UX fix for the SSO/sign-in case (same code path, different 403 body)
Activity
opencode-agent commentedon Oct 25, 2026
Thanks for the detailed write-up, @GladSI. You're asking for a 403 from the OpenCode Console that is neither the SSO case nor an expired key to get a clear message, such as "your Console workspace is restricted, check https://opencode.ai/console or contact [email protected]". Today the raw
Workspace access deniedtext is shown. You also suggest a general fallback for any Console 401/403 the client doesn't recognise.Your reading of the code is right. In v2.1.4,
fetchConfig()andconnectionStatus()handle only the signed-out andSsoRequiredcases, andexplain()rewrites the response only when one of those was reported. So this is a gap in the error messages, not a malfunction, and I've marked it as a feature request for the maintainers to consider.Related issues and PRs:
The 403 itself comes from a restriction on the account, which can't be fixed from the app. If your own workspace is still restricted, please email [email protected], and keep account details out of this public issue.
GladSI commentedon Oct 25, 2026
Follow-up from the reporter: the 403 is credential-scoped, and the fix is an interactive re-login
After
opencode auth login opencode --method device(same account, orgDefault), every Console path works again — while the credential that was active before the re-login still returns the 403:oc_sk_…, created 2026-10-18)GET /console/api/v2/config403 {"_tag":"Forbidden"}200,orgID=wrk_…,orgName="Default"POST /inference/openai/v1/chat/completions, paiddeepseek-v4.1-flash403 permission_error: Workspace access denied200(completion)opencode run -m opencode/deepseek-v4.1-flashAI.Error.Authentication: Workspace access deniedOKopencode run -m opencode/deepseek-v4.1-flash-free403OKSo the restriction is scoped to the stored credential / the workspace it belongs to — not to the machine, the client, or the account as a whole. In my case the recovery was one command, which is exactly why the missing message costs so much: nothing in the failure suggests it, and the credential that has to be replaced is not named anywhere.
Two details that make the message cheaper to write:
metadata.orgID, so the plugin sends nox-org-idheader (packages/core/src/plugin/provider/opencode.ts,headers()), while a device login carriesorgID/orgName. That is precisely the credential shape that can end up workspace-restricted and cannot be described in a warning — which is why the log line is worth enriching too.403from/api/v2/configis the only signal the client gets, and it is currently flattened into the genericfailed to load OpenCode provider configWARN — byte-identical to a transient network failure inopencode.log, so a user pasting their log cannot tell the two apart.Suggested fallback text for a
permission_errorrejection, in addition to therestrictedstatus proposed in the report:The code locations in the original report are still the right place to add it (
fetchConfig()/connectionStatus()/explain()).