Skip to content

Concurrent Auth.set/remove race and silently drop providers in auth.json #30396

Closed as not planned

Description

@azamkhan555622848

Description

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* () {
    const auth = yield* Auth.Service
    yield* 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" },
    )
    const data = 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).

Plugins

No response

OpenCode version

Reproduced on current dev (a78adb1)

Steps to reproduce

  1. Call Auth.set for two+ providers concurrently (e.g. persist one key to two providers during startup)
  2. Read auth.json — only the last write is present; the others are gone

Screenshot and/or share link

No response

Operating System

Windows 11 (logic is OS-independent)

Terminal

Windows Terminal

Activity

  1. github-actions commented on Aug 2, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions