Repository navigation
claude: 馃悰 Read the Keychain before the credentials file - #14
Merged
Merged
Conversation
Claude-Session-Id: 899e5f7a-9099-4d8f-b96d-79291e63b5b4
Claude-Session-Id: 899e5f7a-9099-4d8f-b96d-79291e63b5b4
Claude-Session-Id: 899e5f7a-9099-4d8f-b96d-79291e63b5b4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Isolated Claude runs on this Mac fail with
Failed to authenticate: OAuth token revoked: 145 of 200 capt-hook haiku triage calls failed, and the session reviewer's judge logsfailed=40on every pass. Every host reads~/.claude/.credentials.jsonfirst and the Keychain only when that file is missing. Here the file holds a token that expired on Sep 30, while the Keychain item Claude Code keeps fresh is valid.Claude Code 2.1.293 does the opposite. Its secure storage wraps the Keychain with a plaintext fallback,
M(keychain, plaintext)in the bundle, so it reads the Keychain item first and the file only when the item is missing. This PR flips all three hosts (Python, Go, Rust) to that order, and adds a fallthrough for when a token is rejected anyway.claude_isolation_seednow takescredentials_jsonas an ordered list plusrejected_tokens, and seeds the first access token not yet rejected. When every token has been rejected, it seeds the first one so the run reports the real error. It parses a source only when it gets to it, so a corrupt file behind a good Keychain item no longer matters.claude_auth_rejectedcore op decides whether a run's error is an auth rejection:Failed to authenticate, a revoked OAuth token,authentication_error, orAPI Error: 401.max_attempts, so a call withattempts=1still falls through. A rejected token stays skipped for the rest of the backend (Python) or process (Go, Rust).CliBackendsplitsexecuteandaexecuteinto anexecute_invocationstep that takes the env, so the Claude backend knows which token a run used and an overriddenenv()still applies.The core gains 10 golden vectors, 4 for the seed and 6 for the rejection op. Each host has a test where a fake
clauderejects the Keychain token, and the run succeeds on the credentials file within one attempt. Python also covers async and the case where every source is rejected. Before the fix, the installed 0.17.0 reproduced the failure on this Mac withclaude exited 1: Failed to authenticate: OAuth token revoked.~/.claude/.credentials.jsonis never written or deleted.