Description
Hyper authentication succeeds in both the browser and Crush UI, but immediately afterward Crush enters an unauthorized loop and reports:
unauthorized: {"error":"invalid token: token has invalid claims: token is expired"}
This happens even with:
- fresh auth state
- fresh generated tokens
- correct system clock
- fully restarted Crush process
The issue persists after deleting the local Crush auth state and re-authenticating from scratch.
What happens
- Launch
crush
- Hyper auth flow appears
- Browser opens successfully
- Hyper website shows:
- Crush UI shows:
Authentication successful!
- Immediately afterward when prompting any model, Crush reports:
Unauthorized
Please re-authenticate with Hyper.
- Bottom banner shows:
unauthorized: {"error":"invalid token: token has invalid claims: token is expired"}
Crush then loops back into re-authentication.
What I already tested
Full auth reset
Removed:
~/.local/share/crush/crush.json
Then:
- fully killed all Crush processes
- restarted Crush
- re-authenticated cleanly
Problem still occurs.
Verified local clock
System time is synchronized correctly.
date
date -u
python3 -c "import time; print(int(time.time()))"
JWT expiration timestamps are valid and not expired at issuance time.
Verified generated auth state
Crush regenerates auth state automatically after successful login.
The generated structure contains both:
oauth.access_token
api_key
and both values appear identical.
Expected behavior
After successful Hyper authentication, Crush should enter authenticated state normally and allow chat requests.
Actual behavior
Authentication succeeds visually, but Crush immediately rejects the token as expired and enters a re-authentication loop.
Additional notes
This reproduces consistently after:
- deleting auth state
- restarting Crush
- re-authenticating from scratch
This does not appear to be caused by:
- stale config
- incorrect local clock
- manually edited auth files
- leftover processes
Potentially related to:
- token refresh/session lifecycle
- stale in-memory auth state
- JWT validation logic
- Hyper auth state synchronization
Version
v0.65.3
Environment
macOS, Installed via Homebrew: brew install charmbracelet/tap/crush, Ghostty and Zsh
Description
Hyper authentication succeeds in both the browser and Crush UI, but immediately afterward Crush enters an unauthorized loop and reports:
This happens even with:
The issue persists after deleting the local Crush auth state and re-authenticating from scratch.
What happens
crushCrush then loops back into re-authentication.
What I already tested
Full auth reset
Removed:
~/.local/share/crush/crush.jsonThen:
Problem still occurs.
Verified local clock
System time is synchronized correctly.
date date -u python3 -c "import time; print(int(time.time()))"JWT expiration timestamps are valid and not expired at issuance time.
Verified generated auth state
Crush regenerates auth state automatically after successful login.
The generated structure contains both:
oauth.access_tokenapi_keyand both values appear identical.
Expected behavior
After successful Hyper authentication, Crush should enter authenticated state normally and allow chat requests.
Actual behavior
Authentication succeeds visually, but Crush immediately rejects the token as expired and enters a re-authentication loop.
Additional notes
This reproduces consistently after:
This does not appear to be caused by:
Potentially related to:
Version
v0.65.3
Environment
macOS, Installed via Homebrew: brew install charmbracelet/tap/crush, Ghostty and Zsh