Skip to content

Persistent 401 Invalid API key on macOS even after fresh Claude re-auth + successful OAuth refresh validation #187

Description

@apsoftware123

Description

opencode-claude-auth installs and loads correctly, but all Anthropic requests from OpenCode fail with:
opencode-claude-auth: API 401 for claude-haiku-4-5: {"error":"Invalid API key"}
opencode-claude-auth: API 401 for claude-sonnet-4-6: {"error":"Invalid API key"}
Error: Unauthorized: Invalid API key
Claude Code itself works normally on the same machine/account.
Environment

  • OS: macOS
  • Plugin version: 1.4.9
  • OpenCode version: 1.4.3
  • Claude Code version: 2.1.104
    What I verified
    Claude Code itself works
    claude -p "Reply with exactly OK."
    Output:
    OK.
    Plugin installs and loads
  • Added opencode-claude-auth@latest to ~/.config/opencode/opencode.json
  • Cleared ~/.cache/opencode/packages/opencode-claude-auth@latest/
  • Restarted OpenCode
  • Confirmed package was re-fetched
    Plugin reads credentials successfully
    With CLAUDE_AUTH_DEBUG=1, debug log shows:
  • keychain_list
  • keychain_read
  • credentials_parsed
  • plugin_init
  • auth_loader_called
  • auth_loader_ready
    It is reading:
  • macOS Keychain service: Claude Code-credentials
    Fresh re-auth did not fix it
    I:
  1. deleted the Claude Code-credentials Keychain item
  2. ran claude
  3. logged in again
  4. confirmed the Keychain item was recreated
    OpenCode still returns 401.
    Official-style OAuth refresh validation succeeds
    I tested the plugin’s refresh path equivalent to validate-oauth-refresh and it:
  • successfully minted a fresh access token
  • rotated the refresh token
  • successfully wrote both back to Keychain / auth.json
    Even after that, this still fails:
    opencode run -m "anthropic/claude-sonnet-4-6" "Reply with exactly OK."
    with the same 401 Invalid API key.
    Repro
    export CLAUDE_AUTH_DEBUG=1
    opencode run -m "anthropic/claude-sonnet-4-6" "Reply with exactly OK."
    Expected behavior
    OpenCode should authenticate using Claude Code credentials and return:
    OK.
    Actual behavior
    It consistently returns:
    401 Invalid API key
    Notes / suspicion
    This looks like it is not:
  • an installation issue
  • a stale Keychain issue
  • a failed OAuth refresh issue
    Because:
  • Claude CLI works
  • plugin init works
  • refresh/writeback works
  • only actual OpenCode API requests fail
    So this seems more likely to be a request-construction / header / auth compatibility issue in the plugin for current Anthropic behavior.

Steps to reproduce

  1. Install/configure the plugin:

    • Add opencode-claude-auth@latest to ~/.config/opencode/opencode.json
    • Restart OpenCode
  2. Verify Claude Code itself works:
    claude -p "Reply with exactly OK."
    Expected:
    OK.

  3. Enable plugin debug logging:
    export CLAUDE_AUTH_DEBUG=1

  4. Run a minimal OpenCode request against an Anthropic model:
    opencode run -m "anthropic/claude-sonnet-4-6" "Reply with exactly OK."

  5. Observe failure:
    opencode-claude-auth: API 401 for claude-haiku-4-5: {"error":"Invalid API key"}
    opencode-claude-auth: API 401 for claude-sonnet-4-6: {"error":"Invalid API key"}
    Error: Unauthorized: Invalid API key

  6. Optional stronger repro:

    • Delete Keychain credential:
      security delete-generic-password -s "Claude Code-credentials"
      • Re-auth:
        claude
      • Re-run step 4
    • Same 401 still occurs
  7. Optional stronger repro feat: add release workflow with auto-tagging #2:

    • Run the repo’s OAuth refresh validation / equivalent
    • Confirm it successfully rotates tokens and writes them back
    • Re-run step 4
    • Same 401 still occurs

Operating system

macOS

Plugin version

1.4.9

OpenCode version

1.4.3

Debug logs

Relevant logs
CLI success
$ claude -p "Reply with exactly OK."
OK.
OpenCode failure
$ opencode run -m "anthropic/claude-sonnet-4-6" "Reply with exactly OK."
> [agent name omitted] · claude-sonnet-4-6
opencode-claude-auth: API 401 for claude-haiku-4-5: {"error":"Invalid API key"}
opencode-claude-auth: API 401 for claude-sonnet-4-6: {"error":"Invalid API key"}
Error: Unauthorized: Invalid API key
Debug log excerpt
From ~/.local/share/opencode/claude-auth-debug.log:
{"ts":"2026-04-13T16:32:54.137Z","event":"keychain_list","servicesFound":["Claude Code-credentials"]}
{"ts":"2026-04-13T16:32:54.160Z","event":"keychain_read","service":"Claude Code-credentials","success":true}
{"ts":"2026-04-13T16:32:54.160Z","event":"credentials_parsed","hasAccessToken":true,"hasRefreshToken":true,"hasExpiry":true,"isMcpOnly":false}
{"ts":"2026-04-13T16:32:54.160Z","event":"plugin_init","accountCount":1,"sources":["Claude Code-credentials"],"activeSource":"Claude Code-credentials"}
{"ts":"2026-04-13T16:32:54.161Z","event":"sync_auth_json","path":"~/.local/share/opencode/auth.json","success":true}
{"ts":"2026-04-13T16:32:54.990Z","event":"auth_loader_called","authType":"oauth"}
{"ts":"2026-04-13T16:32:54.990Z","event":"auth_loader_ready","modelCount":23}
{"ts":"2026-04-13T16:32:55.071Z","event":"fetch_credentials","modelId":"claude-haiku-4-5","accessToken":"sk-ant-o...REDACTED","expiresAt":1776125543151}
{"ts":"2026-04-13T16:32:55.480Z","event":"fetch_response","status":401,"modelId":"claude-haiku-4-5","retryAttempt":0}
{"ts":"2026-04-13T16:32:55.481Z","event":"fetch_error_response","status":401,"modelId":"claude-haiku-4-5","message":"{\"error\":\"Invalid API key\"}"}
{"ts":"2026-04-13T16:32:57.637Z","event":"fetch_credentials","modelId":"claude-sonnet-4-6","accessToken":"sk-ant-o...REDACTED","expiresAt":1776125543151}
{"ts":"2026-04-13T16:32:57.648Z","event":"fetch_response","status":401,"modelId":"claude-sonnet-4-6","retryAttempt":0}
{"ts":"2026-04-13T16:32:57.648Z","event":"fetch_error_response","status":401,"modelId":"claude-sonnet-4-6","message":"{\"error\":\"Invalid API key\"}"}
Additional note
I also confirmed:
- deleting and recreating Claude Code-credentials did not fix it
- direct OAuth refresh succeeds and writes back fresh rotated tokens
- even after fresh token writeback, OpenCode still returns 401

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions