Skip to content

Concurrent OAuth refresh from multiple processes kills rotating refresh-token series #49439

Closed as not planned

Description

@okacyzzz-oss

What happens

When several opencode processes share one mcp-auth.json, each process
refreshes OAuth tokens independently on 401. There is no cross-process
single-flight for the refresh transaction (EffectFlock in
packages/opencode/src/mcp/auth.ts only serializes file read/write, not the
refresh itself).

Against an IdP that rotates refresh tokens and revokes the whole family on
reuse, a single overlap is fatal:

  1. Process A and B both read RT1 from the shared file, both POST it to /token.
  2. The winner gets RT2. The loser gets invalid_grant (reuse detected) and the
    IdP kills the entire series.
  3. The SDK (auth() in @modelcontextprotocol/[email protected] src/client/auth.ts) then calls invalidateCredentials('tokens'), wiping stored tokens. The server stays needs_auth` until the user re-authenticates
    manually.

With 7 processes and 300s access tokens, refreshes happen every few minutes
around the clock, so one overlap per day is enough to break the setup
permanently. Observed: 27h of continuous needs_auth, mcp-auth.json left
with only clientInfo + codeVerifier + oauthState.

Related: no retry

Failed tool calls are not retried (withClient in
packages/opencode/src/mcp/index.ts falls back to undefined; connect maps
UnauthorizedError to needs_auth + toast). So the losing call is silently
dropped even when a retry a second later would succeed.

Ask

  • Single-flight refresh across processes sharing one auth file (or at least
    re-read + retry once after a refresh race), and/or
  • Don't wipe stored tokens on a transient refresh failure; keep them so the
    next attempt can use the winner's rotated pair.

Env

opencode 1.18.30, @modelcontextprotocol/sdk 1.29.0, Windows, remote MCP
(StreamableHTTP) + self-hosted OAuth IdP with rotation + reuse detection.

Activity

  1. github-actions commented on Sep 17, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your report adds meaningful new detail (e.g. the specific IdP reuse-detection behavior, the token family invalidation consequence, or the silent-drop in withClient), it may be worth cross-linking rather than closing.

  2. thdxr commented on Oct 11, 2026

    @thdxr
    Member

    Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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