Skip to content

fix: stop infinite interactive-login loop on repeated 401s - #121

Merged
nimrodkor merged 2 commits into
baz-scm:mainfrom
BarGenossar:fix/auth-401-loop
Aug 25, 2026
Merged

nimrodkor merged 2 commits into
baz-scm:mainfrom
BarGenossar:fix/auth-401-loop

Conversation

@BarGenossar

Copy link
Copy Markdown
Contributor

What changed

The axios response interceptor (src/lib/clients/axios/axios-client.ts) reacted to every 401 from 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 401 after a fresh login, the CLI now surfaces a clear error and rejects, instead of looping. The isAuthenticating reset was also moved into a finally block so it is always cleared.

Why

Reported as "the CLI gets stuck in loops on login" (seen on Windows). Reproduced locally:

  • Login itself succeeds and stores a valid, unexpired token (scope: full_access).
  • Requests to https://baz.co/api/v2/... nonetheless return 401.
  • The interceptor re-launched interactive login on each 401 → infinite loop.
  • Each attempt reopened the OAuth callback server on the fixed port 8020, so looping/concurrent attempts collided with EADDRINUSE, wedging the process (the observed "stuck fetching pull requests" hang, with an orphaned process still holding port 8020).

The underlying 401 appears 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

  • This only changes client retry/loop behavior; it does not touch the OAuth flow or token storage.
  • Follow-ups worth considering (not included):
    • Use the stored refresh token for a silent refresh on 401 instead of a full browser flow (a refresh token is saved but never used).
    • Use a dynamic/free callback port instead of the hardcoded 8020, which is more robust on locked-down environments.

🤖 Generated with Claude Code

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>
@baz-reviewer

baz-reviewer Bot commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

Generated description

Prevent the Axios response interceptor from repeatedly launching interactive OAuth authentication after rejected credentials. Mark requests retried after re-authentication, preserve the concurrent-login guard through request replay, and surface a clear error when the Baz API returns another 401.

Topics
TopicDetails
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)
  • src/lib/clients/axios/axios-client.ts
Latest Contributors(0)
UserCommitDate
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)
  • src/lib/clients/axios/axios-client.ts
Latest Contributors(0)
UserCommitDate

Review this PR on Baz | Customize your next review

@baz-reviewer

baz-reviewer Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

⚠️ Advanced Security cannot run on this PR.

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.

Comment thread src/lib/clients/axios/axios-client.ts
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>
Comment thread src/lib/clients/axios/axios-client.ts
@nimrodkor
nimrodkor merged commit 28f76d4 into baz-scm:main Aug 25, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants