fix(auth): unblock [M] manual-fallback API key path + suppress misleading "Claude model unavailable" error#867
Draft
bird-m wants to merge 2 commits into
Draft
Conversation
…-296)
When the OAuth browser redirect fails (e.g. 'Request Header Or Cookie Too Large'
from auth.amplitude.com nginx due to large AMP_*** cookies), users press [M] on
the AuthScreen to enter their project API key manually. Two regressions made
that path looked broken:
1. AuthScreen never closed the manual-fallback form after submit, and the
OAuth-waiting view didn't surface any 'API key saved' acknowledgement —
so the user saw the same 'Enter your project API key' headline + empty
input field after pressing Enter and concluded the wizard was hung
('nothing happens after pasting'). Addressed in a sibling commit on
AuthScreen.tsx.
2. resolveConsoleCredentials returned 'kind: gateway' as long as the session
had a projectApiKey + host, even when credentials.accessToken was empty
(the M-fallback path has no OAuth bearer yet). queryConsole would then
route through queryConsoleWithClaudeAgentSdk → initializeAgent, which
falls through to the local-claude CLI path
(useLocalClaude = !bearerToken && !ANTHROPIC_API_KEY). The Claude Code
SDK then surfaced 'There's an issue with the selected model
(anthropic/claude-sonnet-4-6). It may not exist or you may not have
access to it. Run --model to pick a different model.' — totally
misleading for an unauthenticated user. Guard the gate so the user
instead sees the friendly 'Claude is not available yet — complete
authentication first.' surfaced by queryConsole's existing 'none'
branch.
… line after submission (BA-296)
Pre-fix repro:
1. User on AuthScreen OAuth-waiting view, browser tab returns 400 from
auth.amplitude.com (oversized cookies).
2. User presses [M], pastes their project API key, hits Enter.
3. handleApiKeySubmit fires, setCredentials/persistApiKey succeed, but
manualFallbackOpen stays true and savedKeySource is only rendered
in Step 5 (api_key_notice path) — not in the [M] view.
4. The frame is unchanged: same 'Enter your project API key' headline,
same empty TextInput, no acknowledgement anywhere.
5. User assumes the wizard is broken ('nothing happens after pasting').
Note: the M-fallback path can't on its own satisfy Auth.isComplete —
that gate also needs a resolved org/project tuple, which only browser
OAuth (or stored creds) supplies. So we can't advance the flow on the
strength of the key alone. But we can — and now do — give the user a
visible 'received' signal and tell them what they still need to do.
After this commit:
- handleApiKeySubmit calls setManualFallbackOpen(false) so the
OAuth-waiting view re-renders.
- That view now surfaces a green checkmark line:
✓ API key saved — finish browser sign-in to continue.
above the login URL so the user understands their action landed
and what the next step is.
Added a focused render test
(src/ui/tui/screens/__tests__/AuthScreen.manual-fallback.test.tsx) that
walks the full keystroke path (M → 32-char hex key → Enter) and
asserts both the credential mutation and the acknowledgement copy.
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.
Summary
Two regressions, both reported in
#npx-amplitude-wizard:There's an issue with the selected model (anthropic/claude-sonnet-4-6). It may not exist or you may not have access to it. Run --model to pick a different model.)Both surfaced after the browser sign-in returned
400 Bad Request — Request Header Or Cookie Too Largefromauth.amplitude.com(Colin's workaround: clearAMP_***cookies — pre-existing cookies push the PKCE-laden URL past nginx'slarge_client_header_buffersbudget). With OAuth blocked, the user pressed[M]to enter their API key directly — and ran straight into the two regressions below.Symptom 1 — silent manual-fallback submission
AuthScreen.tsx'shandleApiKeySubmitset credentials and persisted the key, but:manualFallbackOpenstayedtrue, so the screen kept rendering the sameEnter your project API keyheadline + an emptyTextInput.savedKeySource✓ row only renders in Step 5 (api_key_noticepath), not in the[M]view.Net effect: the user saw zero acknowledgement of their action and reasonably assumed the wizard was hung.
Fix: after a successful submit, close the fallback form (
setManualFallbackOpen(false)) and surface a green checkmark line in the OAuth-waiting view above the login URL:Note: the
[M]path can't on its own satisfyAuth.isComplete(that gate also needs a resolved org/project, which only browser OAuth supplies). So we can't advance the flow on the strength of the key alone — but we can give the user a visible "received" signal and tell them what they still need to do.Symptom 2 — Tab/Ask routes to a confusing "Claude model unavailable" error
resolveConsoleCredentialsinsrc/lib/console-query.tsreturnedkind: 'gateway'as long as the session had aprojectApiKey+host, even whencredentials.accessToken === ''(the[M]path has no OAuth bearer yet).queryConsolethen routed throughqueryConsoleWithClaudeAgentSdk→initializeAgent, which falls through to the local-claude CLI path:The Claude Code SDK then surfaced the misleading
There's an issue with the selected model (anthropic/claude-sonnet-4-6)...error — totally orthogonal to what was actually wrong (the user wasn't authenticated).Fix: require a non-empty
credentials.accessTokenfor the gateway branch. When that's missing, fall through tokind: 'none'soqueryConsole's existing early-exit surfaces the friendly:Test plan
src/lib/__tests__/console-query.test.ts— two regression cases pinning theaccessToken-empty path tokind: 'none'and the populated path tokind: 'gateway'.src/ui/tui/screens/__tests__/AuthScreen.manual-fallback.test.tsx— drives the full keystroke path (M→ 32-char hex key → Enter) and asserts both the credential mutation and the acknowledgement copy.pnpm exec prettier --checkandpnpm exec eslintclean on all four touched files; lint-staged hooks ran on each commit.Out of scope / follow-ups
400 Request Header Or Cookie Too Largefromauth.amplitude.comis a server-side nginx / cookie-budget issue, not a wizard bug. Not addressed here.[M]fallback still can't, by design, complete a full wizard run without OAuth (no org/project resolution). The acknowledgement copy now tells the user that explicitly. A bigger product decision to allow API-key-only runs would touchAuth.isComplete, several downstream screens, and analytics scoping — tracked separately.Checklist
pnpm exec prettier --checkandpnpm exec eslintpass on all changed files; targeted Vitest runs green (see above).flows.ts/store.tsnavigation: ran the focused Vitest commands from CLAUDE.md onrouter.test.ts+flow-invariants.test.ts+ the relevantscreens/__tests__/files./reflectchecklist needed — narrow surgical bug fix, no architectural drift.queryConsolesemantics (gateway / direct / none) are preserved; only the gating predicate was tightened.Slack Thread