Skip to content

Hyper auth succeeds but Crush immediately enters unauthorized/token expired loop #2813

@soyomarvaldezg

Description

@soyomarvaldezg

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

  1. Launch crush
  2. Hyper auth flow appears
  3. Browser opens successfully
  4. Hyper website shows:
    Okay! Device activated.
    
  5. Crush UI shows:
    Authentication successful!
    
  6. Immediately afterward when prompting any model, Crush reports:
    Unauthorized
    Please re-authenticate with Hyper.
    
  7. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions