Skip to content

fix: sync OAuth tokens between credential pool and credentials file (salvage #4765)#4981

Merged
teknium1 merged 2 commits intomainfrom
hermes/hermes-766150bd
Apr 4, 2026
Merged

fix: sync OAuth tokens between credential pool and credentials file (salvage #4765)#4981
teknium1 merged 2 commits intomainfrom
hermes/hermes-766150bd

Conversation

@teknium1
Copy link
Copy Markdown
Contributor

@teknium1 teknium1 commented Apr 4, 2026

Salvages #4765 by @netdust. Prevents 24-hour OAuth lockouts when refresh tokens get desynchronized between the credential pool and Claude Code's credentials file.

When any consumer (Claude Code CLI, another profile, fallback path) refreshes a single-use OAuth token, all others' refresh tokens become invalid. The pool now syncs from ~/.claude/.credentials.json before marking entries as exhausted, and writes back after successful refreshes.

23/23 credential pool tests pass. Closes #4765.

netdust and others added 2 commits April 3, 2026 23:25
OAuth refresh tokens are single-use. When multiple consumers share the
same Anthropic OAuth session (credential pool entries, Claude Code CLI,
multiple Hermes profiles), whichever refreshes first invalidates the
refresh token for all others. This causes a cascade:

1. Pool entry tries to refresh with a consumed refresh token → 400
2. Pool marks the credential as "exhausted" with a 24-hour cooldown
3. All subsequent heartbeats skip the credential entirely
4. The fallback to resolve_anthropic_token() only works while the
   access token in ~/.claude/.credentials.json hasn't expired
5. Once it expires, nothing can auto-recover without manual re-login

Fix:
- Add _sync_anthropic_entry_from_credentials_file() to detect when
  ~/.claude/.credentials.json has a newer refresh token and sync it
  into the pool entry, clearing exhaustion status
- After a successful pool refresh, write the new tokens back to
  ~/.claude/.credentials.json so other consumers stay in sync
- On refresh failure, check if the credentials file has a different
  (newer) refresh token and retry once before marking exhausted
- In _available_entries(), sync exhausted claude_code entries from
  the credentials file before applying the 24-hour cooldown, so a
  manual re-login or external refresh immediately unblocks agents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address review feedback: replace bare `except: pass` with a debug
log when the post-retry write-back to ~/.claude/.credentials.json
fails. The write-back is best-effort (token is already resolved),
but logging helps troubleshooting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@teknium1 teknium1 merged commit 78ec8b0 into main Apr 4, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants