Skip to content

Claude Code CLI: OAuth token not auto-refreshed on headless server (refreshToken ignored) #50743

Description

@kubasiak

Description

Claude Code CLI does not auto-refresh OAuth tokens when running on a headless Linux server (GCP VM). The .credentials.json file contains a valid refreshToken, but when the accessToken expires, the CLI returns a 401 instead of refreshing.

Steps to reproduce

  1. Run claude login interactively on a server, authenticate via browser
  2. Wait for accessToken to expire (~6 hours, expiresAt in .credentials.json)
  3. Run claude -p "hello" --output-format stream-json --verbose --dangerously-skip-permissions
  4. Expected: token auto-refreshes using refreshToken
  5. Actual: 401 authentication_error "Invalid authentication credentials"

Environment

  • Claude Code version: 2.1.114
  • OS: Debian 12 (GCP e2-micro VM, headless, no X/display)
  • .credentials.json has valid refreshToken and subscriptionType: "max"
  • No browser available (headless server)

Context

Running Claude Code as a backend agent (called via -p mode from a FastAPI app). The CLI works perfectly when the token is fresh, but silently fails after expiry. Manual token refresh via the OAuth endpoint returns 403 (Cloudflare blocks non-browser requests).

Expected behavior

The CLI should auto-refresh the token using the refreshToken in .credentials.json, similar to how the interactive CLI handles it on desktop machines.

Workaround

Currently falling back to a different agent framework (Kenzan) when OAuth is expired, but this means losing access to Claude Code's full toolset (Read, Write, Edit, Bash).

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already exists

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions