fix: stop infinite interactive-login loop on repeated 401s - #121
Merged
Merged
Conversation
When the Baz API returned 401, the axios response interceptor launched a full interactive browser OAuth flow, retried the request, and — if the server still rejected the token — launched login again, looping forever. Each attempt reopened the OAuth callback server on the fixed port 8020, so concurrent/looping attempts collided with EADDRINUSE and wedged the process (observed on Windows as "stuck fetching pull requests"). Now a request is re-authenticated at most once. If it still 401s after a fresh login, the CLI surfaces a clear error (credentials rejected by the API / possible missing account access) and rejects instead of looping. Also move the isAuthenticating reset into a finally block so it is always cleared. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
|
| Topic | Details | |||
|---|---|---|---|---|
| 401 Re-auth Handling | Stop repeated 401 responses from re-triggering OAuth by marking retried requests and rejecting with an actionable credential/access error.Modified files (1)
Latest Contributors(0)
| |||
| Login Concurrency Guard | Keep isAuthenticating active through authentication and replay, then reliably reset it with finally while preventing concurrent interactive login flows.Modified files (1)
Latest Contributors(0)
|
Contributor
|
Your organization's Advanced Security usage limit has been reached. To continue using Advanced Security reviews, please upgrade your plan or increase your usage limits in your account settings. |
Address review feedback: the interceptor's finally cleared isAuthenticating before the replayed request resolved, so a concurrent 401 could start a second OAuth flow and overwrite the token the first replay was still using. Await the replayed request inside the guarded block so isAuthenticating stays set until it settles. The auth step keeps its own try/catch for the "Authentication failed" message; a repeat 401 on the replay is handled by the _bazAuthRetried branch and propagates without re-triggering login. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nimrodkor
approved these changes
Aug 25, 2026
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.
What changed
The axios response interceptor (
src/lib/clients/axios/axios-client.ts) reacted to every401from the Baz API by launching a full interactive browser OAuth flow, retrying the request, and — when the server still rejected the token — launching login again, indefinitely.This PR makes a request re-authenticate at most once. If it still returns
401after a fresh login, the CLI now surfaces a clear error and rejects, instead of looping. TheisAuthenticatingreset was also moved into afinallyblock so it is always cleared.Why
Reported as "the CLI gets stuck in loops on login" (seen on Windows). Reproduced locally:
scope: full_access).https://baz.co/api/v2/...nonetheless return401.401→ infinite loop.8020, so looping/concurrent attempts collided withEADDRINUSE, wedging the process (the observed "stuck fetching pull requests" hang, with an orphaned process still holding port 8020).The underlying
401appears to be a server-side account/entitlement issue against the migrated v2 API and is out of scope here — but a rejected credential should fail fast with a clear message rather than hang the CLI.Reviewer notes
401instead of a full browser flow (a refresh token is saved but never used).8020, which is more robust on locked-down environments.🤖 Generated with Claude Code