OpenCode (base) provider: migrated Console workspaces always report "session cookie is invalid or expired" (legacy /_server reads only)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 52/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- swift
- Domain
- api, authentication, backend-api-design
Research direction
Start with Sources/CodexBarCore/Providers/OpenCode/OpenCodeUsageFetcher.swift, especially fetchServerText, then compare the Console handling in the OpenCodeGo provider. Review OpenCodeWebCookieSupport and OpenCodeWebParsing.looksSignedOut, and reproduce the issue with codexbar usage --provider opencode --source web --format json. Done means migrated workspaces no longer surface a false invalid-cookie error, while the legacy path remains covered or the provider is clearly deprecated for them.
Written by the indexing model from the issue text.
Description
Summary
The base OpenCode provider (the "OpenCode" entry, not "OpenCode Go") cannot read a workspace that has been migrated to the OpenCode Console. Every refresh reports OpenCode session cookie is invalid or expired. even with a valid signed-in session cookie.
#3796 fixed the Console reads for the OpenCode Go provider, but Sources/CodexBarCore/Providers/OpenCode/OpenCodeUsageFetcher.swift was not touched and still only speaks the legacy SolidStart server functions, which answer as signed out for migrated workspaces.
Environment
- CodexBar 0.69.0 (latest release), app and CLI, macOS 27.0
- Migrated workspace
wrk_01KW2E…("Default"), signed in athttps://opencode.ai/console/… - The Console renders this workspace's usage and pay-as-you-go status fine in the browser
Repro
$ codexbar usage --provider opencode --source web --format json
[{"provider":"opencode","error":{"code":1,"kind":"provider","message":"OpenCode session cookie is invalid or expired."},"source":"web"}]
Identical output with cookieSource: manual and the manual header set to auth=… alone, __Host-console_session=… alone, or both cookies together. Browser auto-import (codexbar cookie refresh --provider opencode --allow-keychain-prompt) reports "No browser session cookie was refreshed" and then fails the same way, so in the UI this is indistinguishable from bad credentials.
Why the credential is not the problem
Using the live __Host-console_session cookie copied from the signed-in console, the Console endpoints that CodexBar already calls for OpenCode Go all answer 200:
| Request | Result |
|---|---|
GET /console/api/orgs |
200 [{"id":"wrk_01KW2E…","name":"Default"}] |
GET /console/api/go/status with x-org-id: wrk_… |
200 with five-hour/week/month meters |
GET /console/api/billing/status |
200, "mode":"pay-as-you-go" |
What the base provider actually requests
Replayed /_server with the same live cookie and the exact headers from OpenCodeUsageFetcher.fetchServerText (X-Server-Id, X-Server-Instance: server-fn:<uuid>, Origin: https://opencode.ai, matching Referer, provider user agent):
1. workspaces server function def39973159c7f0483d8793a822b8dbb10d067e12c65455fcb4608459ba0234f, GET, no args
HTTP 200
;0x000002a6;((self.$R=self.$R||{})["server-fn:…"]=[],($R=>$R[0]=Object.assign(new Error("actor of type \"public\" is not associated with an account"),{stack:"Error: actor of type \"public\" is not associated with an account\n at Object.account (placeholder:78111:15)…
For the auth + __Host-console_session combination I also observed a 302 Found with location: https://opencode.ai/console/login on this call.
2. subscription.get 7abeebee372f304e050aaaf92be863f4a86490e382f8c79db68fd94040d691b4, GET, args=["wrk_01KW2E…"]
HTTP 200
;0x0000010f;((self.$R=self.$R||{})["server-fn:…"]=[],($R=>$R[0]=new Response(null,$R[1]={headers:$R[2]=new Headers($R[3]=[$R[4]=["location","/auth/authorize"]]),status:302,statusText:"Found"}))…
3. billing/customer c83b78a614689c38ebee981f9b39a8b377716db85c1fd7dbab604adc02d3313d, GET, args=["wrk_01KW2E…"]
Same body: 302 Found, location: /auth/authorize.
OpenCodeWebParsing.looksSignedOut matches not associated with an account, actor of type "public" and auth/authorize, so all three paths throw OpenCodeUsageError.invalidCredentials, which surfaces as "OpenCode session cookie is invalid or expired."
Root cause
OpenCodeWebCookieSupport already forwards __Host-console_session (allowlist is auth, __Host-auth, __Host-console_session), so the correct credential does reach the request. The gap is the fetch path only: the base provider contains zero /console/api references on main. #3796 (fix(opencodego): restore Console quota and prepaid balance reads) touched only the OpenCodeGo* files plus the shared cookie importer/support.
Console mapping for the port
Answering the review question on the previous report: keep the base provider supported for migrated workspaces, because every field it reads today has a Console equivalent reachable with a session cookie, except one.
base provider field (legacy /_server) |
Console equivalent | observed value |
|---|---|---|
rollingUsage.usagePercent |
GET /console/api/go/status → access.meters.fiveHour |
usedMicroCents 89062297 / limitMicroCents 1200000000 = 7.4%, resetsAt 2026-09-30T01:31:21Z |
weeklyUsage.usagePercent |
same response → access.meters.week |
703325271 / 3000000000 = 23.4%, resetsAt 2026-10-05T00:00:00Z |
subscription end / renewAt |
access.endsAt (also access.meters.month.resetsAt) |
2026-10-05T02:19:24Z |
monthlyUsage |
GET /console/api/usage/summary → totalCostMicroCents |
6653244286 = $66.53 |
balance |
GET /console/api/billing/status → balanceMicroCents |
0, alongside "mode":"pay-as-you-go" |
hasSubscription |
GET /console/api/orgs/current → hasGoSubscription |
true |
| workspace discovery | GET /console/api/orgs |
[{"id":"wrk_…","name":"Default"}] |
monthlyLimit |
no Console equivalent found | /console/api/budgets, /console/api/billing, /console/api/usage all return 404 |
monthlyLimit is the only real gap; the month meter's limitMicroCents (6000000000 = $60) is the closest analogue if that field is worth keeping, since it is the cycle cap the Console renders itself.
Two details worth carrying into the port:
/console/api/usage/summaryaccepts a range: the default answeredtotalCostMicroCents=6653244286(26,316 requests) while?range=30danswered5520922478(18,733 requests).period=,from=/to=,window=andlimit=are ignored,range=monthis a 400, so the monthly figure needsrangeset explicitly instead of trusting the default. The counter is live: it grew by 55,798,838 micro-cents (about $0.56) between two probes minutes apart.OpenCodeGoZenBalanceParseralready divides the same 1e8 scale and/console/api/go/statusis scoped withx-org-id: wrk_…, so the base provider can reuse that parsing and needs/console/api/orgsonly for discovery. The legacy/_serverpath can stay as a fallback for un-migrated workspaces, butlooksSignedOutmust stop treating its payload as an auth failure, otherwise migrated users keep seeing "session cookie is invalid or expired" instead of a migration message.
Expected
Either:
- Port the Console reads into the base provider the way
OpenCodeGodoes (/console/api/orgs,/console/api/go/status,/console/api/billing/status,/console/api/usage/summary, micro-cent conversion,x-org-idscoping), or - Mark the base OpenCode provider deprecated/hidden for migrated workspaces so it stops reporting a false "credentials invalid or expired" state.
I suspect this affects every workspace with migrated_at set, not just mine.
Workaround
$ codexbar config disable --provider opencode
which stops the failure on every refresh. OpenCode Go meters continue to work through the opencodego provider.
- Dominant language
- Swift
- Stars
- 21.9k
- Forks
- 2k
- Avg merge
- 21h 23m
- Merged PRs (30d)
- 438
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
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.
More from steipete/CodexBar
-
clawsweeper:needs-maintainer-review clawsweeper:needs-product-decision clawsweeper:no-new-fix-pr clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster P2
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
steipete/CodexBar#3349 · 2 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
clawsweeper:needs-maintainer-review clawsweeper:needs-product-decision clawsweeper:no-new-fix-pr impact:ux-friction issue-rating: 🌊 off-meta tidepool P3
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
steipete/CodexBar#2860 · 2 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
clawsweeper:needs-maintainer-review clawsweeper:needs-product-decision clawsweeper:needs-security-review clawsweeper:no-new-fix-pr impact:auth-provider impact:security issue-rating: 🌊 off-meta tidepool P2
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
steipete/CodexBar#2429 · 2 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
clawsweeper:needs-info clawsweeper:needs-maintainer-review clawsweeper:no-new-fix-pr impact:auth-provider impact:ux-friction issue-rating: 🦐 gold shrimp P2
Difficulty 3/5 1-2 days Newbie friendliness 72/100
steipete/CodexBar#4129 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day
All issues in steipete/CodexBar
Similar issues
-
area: agents area: cli bug difficulty:2 help wanted S3: minor
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
manaflow-ai/cmux#15718 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
mozilla-mobile/firefox-ios#35850 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
chattymin/PokeTokenBar#385 ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
appandflow/stim#1941 ·
Maintainers usually reply within 1 day
-
product / avatars product / self-hosted product / storage
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
appwrite/appwrite#13985 · 1 comment ·
Maintainers usually reply within 1 day