Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

OpenCode (base) provider: migrated Console workspaces always report "session cookie is invalid or expired" (legacy /_server reads only)

Open
#4,131 0 comments 0 reactions 0 assignees View on GitHub

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

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 at https://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/summary accepts a range: the default answered totalCostMicroCents=6653244286 (26,316 requests) while ?range=30d answered 5520922478 (18,733 requests). period=, from=/to=, window= and limit= are ignored, range=month is a 400, so the monthly figure needs range set 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.
  • OpenCodeGoZenBalanceParser already divides the same 1e8 scale and /console/api/go/status is scoped with x-org-id: wrk_…, so the base provider can reuse that parsing and needs /console/api/orgs only for discovery. The legacy /_server path can stay as a fallback for un-migrated workspaces, but looksSignedOut must 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:

  1. Port the Console reads into the base provider the way OpenCodeGo does (/console/api/orgs, /console/api/go/status, /console/api/billing/status, /console/api/usage/summary, micro-cent conversion, x-org-id scoping), or
  2. 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from steipete/CodexBar

All issues in steipete/CodexBar

Similar issues

More Swift issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.