Skip to content

fix(credentials): Use an authenticated Claude probe to refresh tokens - #25

Merged
euxaristia merged 1 commit into
mainfrom
fix/claude-token-refresh-probe
Aug 12, 2026
Merged

fix(credentials): Use an authenticated Claude probe to refresh tokens#25
euxaristia merged 1 commit into
mainfrom
fix/claude-token-refresh-probe

Conversation

@euxaristia

Copy link
Copy Markdown
Owner

Summary

limits could not refresh an expired Claude token, because both refresh candidates only read local state. claude auth status prints the stored auth state and exits, despite a code comment claiming it "probes Anthropic auth servers and forces Claude Code CLI to refresh expired OAuth tokens", and claude --version never touches auth at all. When the token in ~/.claude/.credentials.json expired, EnsureTokenReady ran a refresh that could not succeed and the provider stayed degraded until the user happened to run Claude Code interactively.

This is the same class of bug as #23, where grok --version was replaced with an authenticated grok models probe. This change gives Claude the same treatment: probe with a command that actually resolves the account, so the CLI refreshes the token as a side effect.

Each candidate was run against a home directory holding an expired access token paired with a deliberately invalid refresh token, then the credentials file was checked for a refresh attempt:

command attempts refresh
claude auth status no
claude --version no
claude agents --json no
claude doctor yes
claude mcp list yes

doctor is the primary probe, as it resolves the account and completes in about a second. mcp list is the fallback.

Fixes #24

Changes

pkg/credentials/credentials.go

  • Replace the Claude refresh candidates auth status and --version with doctor and mcp list.
  • Correct the comment, which asserted behavior the commands do not have, and record which commands are inert so the reasoning is not lost.

pkg/credentials/credentials_test.go

  • TestGetCliCandidatesClaude now requires a real refresh probe and rejects the three commands proven inert, so a future edit cannot quietly reintroduce a probe that never refreshes.
  • Update TestForceRefreshViaCliHeadlessCandidateValidation's fake CLI to model the new candidate pair: doctor runs without refreshing, mcp list writes a fresh token. The call-log assertion still proves both candidates ran, in order.

Test plan

gofmt -l .
go vet ./...
go test ./...

All pass locally.

Verify the new test catches the old bug, by reverting only the source change:

git stash push pkg/credentials/credentials.go
go test ./pkg/credentials/ -run TestGetCliCandidatesClaude   # fails
git stash pop
go test ./pkg/credentials/ -run TestGetCliCandidatesClaude   # passes

Manual verification against a real account:

go build -o dist/limits .
./dist/limits --no-color -p claude

Reports the session and weekly windows with no degraded state.

Note: CI cannot run on this repository at the moment. GitHub Actions reports "The job was not started because recent account payments have failed or your spending limit needs to be increased", which is also why the checks on #23 showed red. The verification above was therefore run locally.

The Claude refresh candidates only read local state, so neither could
refresh an expired token in ~/.claude/.credentials.json. "auth status"
prints the stored auth state and exits, despite a comment claiming it
probes Anthropic auth servers, and "--version" never touches auth at all.
When the token expired, EnsureTokenReady ran a refresh that could not
succeed and the provider stayed degraded.

Running each candidate against an expired access token paired with an
invalid refresh token shows which ones attempt a refresh: "auth status",
"--version" and "agents --json" leave the token untouched, while "doctor"
and "mcp list" both try. Use "doctor" as the primary probe, since it
resolves the account and completes quickly, and keep "mcp list" as a
fallback.

The candidate test now also rejects the three commands proven inert, so a
future edit cannot quietly reintroduce a probe that never refreshes.

Refs #24
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 2 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8cfed5c4-ae3b-43ab-aeaf-6f61b15b9426

📥 Commits

Reviewing files that changed from the base of the PR and between 8ea3b12 and 9eb0881.

📒 Files selected for processing (2)
  • pkg/credentials/credentials.go
  • pkg/credentials/credentials_test.go

Comment @coderabbitai help to get the list of available commands.

@euxaristia
euxaristia marked this pull request as ready for review August 12, 2026 01:10
@euxaristia
euxaristia merged commit e049ef3 into main Aug 12, 2026
0 of 4 checks passed
@euxaristia
euxaristia deleted the fix/claude-token-refresh-probe branch August 12, 2026 01:11
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.

Claude token refresh probes cannot refresh an expired token

1 participant