[BUG] OAuth token expiration disrupts autonomous workflows – refresh token handling needed

Open 💬 25 comments Opened Nov 26, 2025 by brupelo

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

OAuth token expiration disrupts autonomous workflows – refresh token handling needed

Environment:

  • Claude Code version: 2.0.45
  • Platform: Docker (headless/autonomous operation)

Problem

OAuth tokens expire during long-running autonomous tasks, causing 401 authentication_error failures that require manual /login intervention. When running multiple concurrent Claude Code instances dispatching work over extended periods (hours/days), token expiration halts all in-progress tasks simultaneously, leaving work in incomplete states.

API Error: 401 {"type":"error","error":{"type":"authentication_error","message":"OAuth token has expired. Please obtain a new token or refresh your existing token."},"request_id":"..."}

Combined with occasional 500 errors (separate issue, but compounding), sustained autonomous operation is currently not viable.

Why This Feels Like a Bug (Not Just a Security Feature)

I understand short-lived tokens are a security best practice—limiting exposure if credentials leak. However:

  1. OAuth has a standard solution for this: refresh tokens. Short-lived access tokens + automatic refresh gives you both security AND seamless operation. The current implementation seems to require manual re-authentication rather than handling refresh transparently.
  1. The failure mode is destructive. Tasks don't gracefully pause and resume—they leave branches and work in half-finished states. If the intent is to require periodic human check-ins, a cleaner approach would be to pause work cleanly and queue for resumption, not crash mid-task.
  1. No visibility into expiration timing. I can't plan around this because I don't know when expiration will occur. If human oversight is the goal, at least let me see "token expires in X hours" so I can schedule accordingly.
  1. If limiting autonomous operation is intentional, there are better mechanisms: explicit autonomous-mode opt-in, spending caps, task duration limits, or configurable session lengths. The current behavior doesn't prevent autonomous use—it just makes it frustrating and wastes work.

What I'm Trying to Do

Run multiple Claude Code instances in Docker containers, dispatching and processing issues continuously over several days. This requires:

  • Reliable authentication that doesn't require babysitting
  • Graceful handling of transient failures (auth, network, API errors)
  • Ability to resume interrupted work

Question for Maintainers

Is the current behavior intentional to discourage long-running autonomous agents, or is this simply an implementation gap in the OAuth flow? If it's intentional, I'd appreciate understanding the reasoning—and would suggest that explicit guardrails (spending limits, duration caps, opt-in autonomous mode) would be a better UX than silent auth failures.

---

This is currently a significant blocker for autonomous agentic workflows. Happy to provide more details or test any proposed fixes.

What Should Happen?

Proposed Solutions (Pick Any)

  1. Implement proper refresh token handling – Transparently refresh access tokens before expiration. This is the standard OAuth pattern.
  1. Expose token lifetime configuration – Let users set token expiration duration (like Azure DevOps, GitHub PATs, etc.). Those running supervised can use short tokens; those running autonomous can accept the security trade-off.
  1. Add session resumption – If auth fails mid-task, persist state so work can resume after re-authentication rather than leaving repos in broken states.
  1. Show expiration time – At minimum, display when the current token expires (/status or similar) so users can plan around it.

Error Messages/Logs

API Error: 401 {"type":"error","error":{"type":"authentication_error","message":"OAuth token has expired. Please obtain a new token or refresh your existing
     token."},"request_id":"req_011CVWAKo6VpooYthEXLYEYe"} · Please run /login

Steps to Reproduce

Environment setup:

  1. Run Claude Code in a Docker container (headless, no interactive terminal)
  2. Authenticate via /login
  3. Dispatch one or more long-running tasks (e.g., complex refactoring, multi-file changes, issue-driven workflows)

Reproduction:

  1. Start a task that takes 30+ minutes, or start multiple concurrent tasks
  2. Leave running unattended for several hours (I've seen this trigger within 2-4 hours, but exact timing is unpredictable)
  3. Return to find all instances stopped with 401 authentication_error

Observed behavior:

  • All running tasks fail simultaneously with OAuth expiration error
  • Work is left in incomplete state (partial commits, uncommitted changes, mid-process branches)
  • Requires manual /login to resume
  • No warning before expiration occurs

Expected behavior:

  • Token refreshes automatically before expiration
  • Or: tasks pause gracefully and resume after re-authentication
  • Or: at minimum, token expiration time is visible so users can plan around it

Frequency: Happens consistently when running tasks over extended periods. Not a rare edge case.

Note: Exact expiration timing is unknown—this is part of the problem. If there's a way to inspect token TTL, please share and I can provide more precise reproduction timing.

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.0.45 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

_No response_

View original on GitHub ↗

25 Comments

onikiienko · 7 months ago

We also observe this problem in Xcode. Have to sign out and log in once a day.

maxjendrall · 7 months ago

If I am not entirely wrong, I was able to solve it by doing "claude setup-token" instead of /login within the interactive shell.

It says: "Your OAuth token (valid for 1 year)" and "✓ Long-lived authentication token created successfully!"

lsscodes · 7 months ago

@toorusr I tried your suggestion and was able to create a long-lived aut token, but i am still getting this error in claude(code) destop app

<img width="1256" height="334" alt="Image" src="https://github.com/user-attachments/assets/fa838fb8-2756-49d8-9e51-473a684d24c6" />

brupelo · 7 months ago

Hi guys, thanks for the feedback and suggestions! That sounds really good—exactly what was needed. /login won’t cut it. I haven’t had time to try it yet, but I’ll give it a shot once my usage is back… crazy how fast the Max plan gets used up—four days of idling already because all models maxed out in a blink of an eye. IMHO It’s quite expensive for the limited usage you get from the Claude API and the extra usage is very expensive, times when i used maxed out in few minutes, but that’s off-topic.

With this approach, I assume you’d be able to use a single authorization token that you can easily revoke from https://claude.ai/settings/claude-code and share across different agents, right?

Right now, I’m running multiple Docker environments, and in each one I have to log in manually once and then share credentials across all containers. It would be great if I could instead share a single token across all environments.

As long as this provides proper control over expiration and revocation, it sounds like the right solution.

mitchcapper · 7 months ago

manual long lived token is really not the solution plenty of apps used refresh tokens and can properly refresh the session. Case and point simply restarted claude code and it is good to go, there is no reason it shouldn't be able to keep its session alive. @lsscodes the desktop app doesn't have a similar option thus the continued issue.

ftballguy45 · 7 months ago

now getting asked daily to relogin to claude desktop 👎

ElCativoGER · 6 months ago

I am using claude Desktop and can´t login to Code. Everything ist fin but Code is not working. Always getting Token failure...
/login does nothing
Manually logoff login does nothing, still error.
Can´t work anymore, please help.
Running on Windows with Google Auth.

PowerAppsDarren · 6 months ago

I'm on the 20x Max Plan.

This has become worse for recently. I'm burning through all my credits for spawned sub agents, then those agents are coming back with oauth error telling me to log in. I'm sorry, it is not feasible to sit at my computer and monitor for these 401 errors 20 or more times a day. We shouldn't have to.

API Error: 401 {"type":"error","error":{"type":"authentication_error","message":"OAuth token has expired. Please obtain a new token or refresh your existing token."},"request_id":"req_011CWR6QbR9zivmQtHS6Tzck"} · Please run /login



  Time: 2025-12-25 19:26 | Claude Agents: 72 active

  Repository Progress

  +-------------------+--------+------+------------------------------------+
  | Repository        | Status | Iter | Progress                           |
  +-------------------+--------+------+------------------------------------+
  | PROJECT-NAME      | [OK]   |  331 | ████████████████████████████████ * |
  | PROJECT-NAME      | [OK]   |  331 | ████████████████████████████████ * |
  | PROJECT-NAME      | [OK]   |  313 | ██████████████████████████████   * |
  | PROJECT-NAME      | [OK]   |   69 | ███████                            |
  | PROJECT-NAME      | [OK]   |   69 | ███████                            |
  | PROJECT-NAME      | [OK]   |   69 | ███████                            |
  | PROJECT-NAME      | [>>]   |   68 | ██████▓                            |
  | PROJECT-NAME      | [OK]   |   68 | ███████                            |
  | PROJECT-NAME      | [OK]   |   67 | ███████                            |
  | PROJECT-NAME      | [OK]   |   67 | ███████                            |
  | PROJECT-NAME      | [OK]   |   66 | ██████                             |
  | PROJECT-NAME      | [>>]   |   65 | ██████▓                            |
  | PROJECT-NAME      | [OK]   |   59 | ██████                             |
  | PROJECT-NAME      | [OK]   |   59 | ██████                             |
  +-------------------+--------+------+------------------------------------+
  [OK] = completed | [>>] = running | * = high activity

  Warning: Zero Progress Alert

  +--------------------------------------------------------------+
  | [!] ZERO_PROGRESS: 744 consecutive sessions with 0 files     |
  |     modified. Agents are running but not producing output.   |
  +--------------------------------------------------------------+

  The cost monitoring is flagging:
  - 744 consecutive sessions with no file changes
  - Burn rate warnings (cost calculation seems off - likely a bug in the metrics)

----

Claude CLI auth is expired and sessions are still marked completed: repeated API Error: 401 ... Please run /login in iteration reports like 2025-12-25-061-review-the.md and 2025-12-25-023-add-tests.md; agent.py treats any response text as “completed,” so these failures keep re-queuing with zero edits.
Zero-progress count only resets on nonzero files_modified (orchestrator_monitor.py), so auth-failed or read-only runs quickly compound to 744.
File-change tracking only counts Edit/Write tool calls with file_path (agent.py), while many sessions only show Bash/Read/TodoWrite/mcp__... tools (e.g., 2025-12-25-060-add-tests.md), so real changes via shell/MCP are missed.
MCP output shows allowed dir /C/src while repos are A:\src (see 2025-12-25-060-review-review.md), which can block file writes even when auth works.
mission.max_cycles_per_repo isn’t enforced; cycle-mode re-queues unconditionally in orchestrator.py, amplifying repeated zero-output sessions.
Burn-rate warnings use estimated tokens/hour but label them as dollars (orchestrator_monitor.py, cost_tracker.py), which matches the “cost calc seems off” complaint.
Recommended Next Steps

Re-authenticate Claude CLI (claude /login or ensure ANTHROPIC_API_KEY is valid) and verify a single run produces tool calls and no 401s.
Treat auth failures as error in agent.py (e.g., detect authentication_error in response text) so the orchestrator doesn’t re-queue failed sessions.
Track file changes via git status --porcelain per repo (or expand tool-name/path matching) so zero-progress reflects real output.
Enforce mission.max_cycles_per_repo and/or stop after N consecutive zero-change sessions to prevent infinite cycling.
Fix burn-rate units (tokens/hour vs USD) and use CostTracker.cost_usd if you want dollar-based alerts.

<img width="1427" height="564" alt="Image" src="https://github.com/user-attachments/assets/99503ebf-0366-4bf0-934f-b386e3ca4782" />

<img width="1006" height="659" alt="Image" src="https://github.com/user-attachments/assets/5b421dff-3307-4266-b18f-04581f2444bc" />

BlindGuyNW · 6 months ago

Just chiming in here as a desktop user who's noticed this (exclusively on desktop) recently. It makes using the app very frustrating as I can't seem to return to a session after it happens.

zonnenberg · 6 months ago

<img width="783" height="79" alt="Image" src="https://github.com/user-attachments/assets/747e30a1-1a92-4d9d-bfe8-7c976f75bf28" />

Same here in Claude Code Desktop. Yesterday I started a few sessions, and now all those existing sessions don't work anymore. After starting a new session and logging in, only that session works.

Steps to reproduce:

  1. Open Claude Code Desktop
  2. Authenticate with Google OAuth
  3. Start one or more sessions and use them normally
  4. Wait approximately 24 hours (or until OAuth token expires)
  5. Open Claude Code Desktop again
  6. Try to continue working in one of the existing sessions from step 3 (even /login does nothing)
  7. Observe the error
  8. Start a new session – observe that it works correctly
  9. Existing sessions still not working, giving the same error message again

Update: Temp workaround is to go to the folder and start Claude CLI with claude -r, then continue the session from there.

brupelo · 5 months ago

Hi everyone,

This issue is back and is becoming pretty disruptive.

When using:

bpl-a1@03b0cc2f2868:~$ cld --version
2.1.14 (Claude Code)

I start getting OAuth expiration errors (401 Unauthorized) after a few hours of work, especially when I’m running multiple containers.

With version 2.0.76, claude setup-token worked reliably for me after doing claude setup-token. That no longer seems to be the case, so I may be missing something—or behavior has changed.

I did find something that sheds a bit of light on what’s happening, though.

from datetime import datetime
from zoneinfo import ZoneInfo


def decode_token_expiration(token_expiration, zone_info="Europe/Paris"):
    return datetime.fromtimestamp(token_expiration / 1000, tz=ZoneInfo(zone_info))


if __name__ == "__main__":
    lst = [1769097912282, 1769057661217]

    for t in lst:
        print(decode_token_expiration(t))

This lets you decode the token expiration timestamp from ~/.claude/.credentials.json. At the very least, it helps understand when the token expires.

That said, this expiration information really should be available in a human-readable form directly in Claude Code.

More importantly:
Does anyone know how claude setup-token actually works internally? It behaved fine for me on 2.0.76, but on 2.1.14 I’m consistently hitting token expiration issues again. I’d really like to understand what changed and how to properly control or avoid this bug.

Also, the above examples are the timestamps from 1 container that's working cos it expires at 2026-01-22 17:05:12.282000+01:00 and the other giving 401 cos it's already expired at 2026-01-22 05:54:21.217000+01:00 . Now, in the one that's working when i run /usage i can see the metric... in the one i can't i just see:

```
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Settings: Status Config Usage (←/→ or tab to cycle)

Loading usage data…

esc to cancel


and it gets stuck... 
Pxmme · 5 months ago

This needs to get fixed.

Emk0oo · 5 months ago

Same here from Claude extension in VSCode. I can put the token when login in then I can access the tool but when launching my prompt I'm disconnected instantly with that same error

pawelbaranski · 5 months ago

Same here in Claude extension - VSCode.

"Failed to authenticate. API Error: 401
{
  "type":"error",
  "error": {"type":"authentication_error","message":"OAuth token has expired. Please obtain a new token or refresh your existing token."},
  "request_id":"req_011CXnxyuqU2unb1pgHiTdum"
}"

I am using "Anthropic Console" option to integrate, I am redirected to proper page, I accept what I need, then success page appears, but the Claude stil does not work and stops with that error.

mieubrisse · 5 months ago

I'm getting the dreaded

API Error: 401 {"type":"error","error":{"type":"authentication_error","message":"OAuth token has expired. Please obtain a new token or refresh your existing token."}

multiple times per day now. this is pretty crazy.

WynnD · 4 months ago

I have this same issue on Ubuntu 25.10 using Claude Code version 2.1.50

mieubrisse · 4 months ago

I worked around this using claude setup-token and then feeding it in as the CLAUDE_CODE_OAUTH_TOKEN environment variable. It skips all the "OAuth tokens invalidating each other", but has the downside that it doesn't allow /usage

mieubrisse · 4 months ago

Same issue being tracked on #24317 , and there has more forensics on exactly why this happens

prong-raft-squishy · 4 months ago

Adding data from an autonomous workflow use case. I run Claude Code headless via launchd (macOS cron equivalent) for scheduled maintenance tasks — security audits, fleet health checks, content processing. These are non-interactive sessions launched with claude -p through a wrapper script.

The pattern: a 60-second auth pre-flight check passes, then the actual session runs for 1-3 hours and dies mid-execution with OAuth token has expired. This affects multiple scheduled jobs per week — out of 15 scheduled skills, auth expiry is the #1 failure mode (3 of 5 recent failures).

The pre-flight check is essentially worthless for long sessions because it only proves the token is valid right now, not that it will survive the session duration. A token refresh mechanism or longer TTL would make autonomous Claude Code workflows significantly more reliable. Currently there's no recovery path — the session just dies and the work is lost.

mieubrisse · 4 months ago

Prong are you using the token from setup-token?

On Mon, Feb 23, 2026, 20:54 prong-raft-squishy @.***>
wrote:

prong-raft-squishy left a comment (anthropics/claude-code#12447) <https://github.com/anthropics/claude-code/issues/12447#issuecomment-3948022144> Adding data from an autonomous workflow use case. I run Claude Code headless via launchd (macOS cron equivalent) for scheduled maintenance tasks — security audits, fleet health checks, content processing. These are non-interactive sessions launched with claude -p through a wrapper script. The pattern: a 60-second auth pre-flight check passes, then the actual session runs for 1-3 hours and dies mid-execution with OAuth token has expired. This affects multiple scheduled jobs per week — out of 15 scheduled skills, auth expiry is the #1 <https://github.com/anthropics/claude-code/pull/1> failure mode (3 of 5 recent failures). The pre-flight check is essentially worthless for long sessions because it only proves the token is valid right now, not that it will survive the session duration. A token refresh mechanism or longer TTL would make autonomous Claude Code workflows significantly more reliable. Currently there's no recovery path — the session just dies and the work is lost. — Reply to this email directly, view it on GitHub <https://github.com/anthropics/claude-code/issues/12447#issuecomment-3948022144>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAIW3KO3BMKFI4UTTUPSV7T4NOHL7AVCNFSM6AAAAACNHN3OIWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTSNBYGAZDEMJUGQ> . You are receiving this because you commented.Message ID: @.***>
lonetis · 4 months ago

Do you use the same refresh token across multiple isolated Claude Code instances? Claude uses refresh token rotation (https://datatracker.ietf.org/doc/html/rfc9700#section-2.2.2). When a client redeems a refresh token, the server invalidates it and issues a new one. As a result, two machines can’t share the same refresh token. One machine redeems it and stores the rotated token, while the other keeps using the old token and fails.

mieubrisse · 4 months ago

The result of claude setup-token is valid for a year; I haven't had a problem with it since setting it up

oorestisime · 4 months ago
The result of claude setup-token is valid for a year; I haven't had a problem with it since setting it up

Is this an api token or a subscription token ?

mieubrisse · 4 months ago

A subscription token. It uses the same limits as your Pro/Max plan.

On Wed, Mar 11, 2026 at 3:40 AM Orestis Ioannou @.***>
wrote:

oorestisime left a comment (anthropics/claude-code#12447) <https://github.com/anthropics/claude-code/issues/12447#issuecomment-4036876910> The result of claude setup-token is valid for a year; I haven't had a problem with it since setting it up Is this an api token or a subscription token ? — Reply to this email directly, view it on GitHub <https://github.com/anthropics/claude-code/issues/12447#issuecomment-4036876910>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAIW3KOUTKGXIJXAVMYGZAD4QEC6LAVCNFSM6AAAAACNHN3OIWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DAMZWHA3TMOJRGA> . You are receiving this because you commented.Message ID: @.***>
42piratas · 3 months ago

Any updates on this?