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
Concurrent Auth.set/remove race and silently drop providers in auth.json #30396
I'm an AI/software developer and researcher building an application on top of opencode, and hit this in my app when several provider auths get written in parallel during startup.
Auth.set / Auth.remove in packages/opencode/src/auth/index.ts do an unlocked read-modify-write of auth.json: each reads the whole map via all(), mutates in memory, then writeJsons it. Two set() calls running concurrently read the same snapshot, so the second write overwrites the first and a provider silently vanishes. And since writeJson is a plain non-atomic writeFile, a crash mid-write can truncate the file — all() then returns {} (bad entries are dropped by Schema.decodeUnknownOption), surfacing as an empty model picker and "failed to load" errors.
Minimal in-repo proof — three concurrent set calls, assert all three survive — fails on dev (only the last write lands):
it.instance("set is safe under concurrent calls",()=>Effect.gen(function*(){constauth=yield*Auth.Serviceyield*Effect.all([auth.set("anthropic",{type: "api",key: "k1"}),auth.set("openai",{type: "api",key: "k2"}),auth.set("google",{type: "api",key: "k3"}),],{concurrency: "unbounded"},)constdata=yield*auth.all()expect(Object.keys(data).sort()).toEqual(["anthropic","google","openai"])}),)
Happy to open a PR — fix serializes set/remove with a Semaphore in the Auth layer (same pattern snapshot already uses).
Activity
github-actions commentedon Aug 2, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.