fix(web): expired token on load → Login instead of stuck on Loading#182
Merged
Conversation
…creen
Opening the app with an already-expired/invalid legacy localStorage token
left the user permanently on the "Loading…" screen. useProfile swallows the
/api/profile 401 and sets loading=false with profile=null; the combined
`profileLoading || !profile` render gate then trapped on LoadingScreen forever.
The global onAuthEvent('unauthorized') handler that normally clears the token
races the useProfile fetch on a fresh page-load (the handler can be null when
the 401 lands), so the redirect was dropped.
Split the render gate so a settled-but-null profile renders Login
deterministically, and add an effect that clears the dead credential
(signOut, never during render) once the load settles with no profile. signOut
nulls token+user so the effect's `(token||user)` guard goes false on the next
render → no loop. Happy path is unaffected: useProfile never nulls profile
after a successful load, so a logged-in user can't be bounced to Login on a
transient refetch blip.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Third facet of the auth-expiry hardening (after #180 blank-guard + #181 non-array crash). Opening the app with a dead/expired
remo_tokenleft the user stuck on the 'Loading…' screen forever.Cause:
useProfileswallows the /api/profile 401 →loading=false, profile=null; App gateprofileLoading || !profiletrapped on LoadingScreen. The global 401→signOut handler races useProfile's fetch on fresh load, so the redirect was dropped and the token never cleared.Fix (App.tsx, +24/−1): split the gate (
profileLoading→Loading, then!profile→), plus an effect that clears the dead credential via signOut() when load settles with no profile but a token present (outside render; no loop — verified). Happy path unaffected (useProfile never nulls profile after a successful load).Verified (Playwright, local build, /api/profile→401): stale token on #/ and #/settings → lands on Login, token cleared to null, no loop/crash/blank. no-token load → Login. tsc 0, build 0.
🤖 Generated with Claude Code