[BUG] Sandbox/scratchpad state lost after long idle period (weekly usage limit reset), despite same continuous conversation

Status Open
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Jul 15, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

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?

Summary
After hitting the weekly usage limit and waiting ~1.5 days for it to reset, I resumed
the same conversation (same chat thread, not a new one) and found that Claude's
session-scoped scratchpad directory had been wiped. A working file that had been
built up over several turns (an HTML artifact with multiple rounds of edits) was
gone. The directory path itself had a new session UUID, distinct from the one used
earlier in the same conversation.

Impact
Claude had to re-fetch the last-published version of the artifact from its hosted
URL and manually reapply several rounds of prior edits from conversation context to
reconstruct the file. This cost a significant number of extra tokens (15k+) purely
to recover state that should have persisted across a usage-limit wait, since the
conversation itself was never ended or restarted by me.

Expected behavior
Session/sandbox state (or at minimum the scratchpad working directory) should
persist across a usage-limit cooldown within the same continuous conversation,
or the user/model should be clearly warned that it won't.

Environment

  • Claude Code (web-based session, Claude Sonnet 5)
  • Working directory: local macOS project folder
  • Scratchpad path observed to change from one session-UUID subdirectory to another

after the wait, with the original left empty

What Should Happen?

Expected behavior
Session/sandbox state (or at minimum the scratchpad working directory) should
persist across a usage-limit cooldown within the same continuous conversation,
or the user/model should be clearly warned that it won't.

Error Messages/Logs

None noted, beyond Claude stating that the scratchpad was no longer showing the file, and it had to be recreated from the existing communication chat thread.

Steps to Reproduce

Environment

  • Claude Code (web-based session, Claude Sonnet 5)
  • Working directory: local macOS project folder
  • Scratchpad path observed to change from one session-UUID subdirectory to another

after the wait, with the original left empty

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

1.21459.0

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

3 Comments

pristineremodelco · 1 month ago

Follow-up with additional detail from working through this with Claude after
filing the original report.

Version clarification
When I went to file this report, the submission page instructed me to update
Claude Desktop first. I want to be clear about the sequence: I updated AFTER
the sandbox loss had already occurred, only because the report page told me
to before I could file. The update was not something that happened during or
before the original issue, and did not cause it.

  • Version active during the actual sandbox loss: unrecoverable — the updater

(Squirrel/ShipIt) had already deleted the previous app bundle by the time I
checked, so there's no way to confirm the exact prior version number.

  • Version after updating (current, at time of this comment): Claude Desktop

1.21459.0, bundled Claude Code 2.1.209.

Hardware/OS environment
Flagging this in case it's hardware-specific rather than universal:

  • Mac mini, Model Identifier Mac16,10
  • Apple M4 chip, 16 GB memory
  • macOS 26.5.2 (Build 25F84)

Reproduction constraint
I wasn't able to cleanly re-trigger the original scenario on demand, because
doing so requires hitting the weekly usage limit and waiting out a ~1.5 day
reset window again — I couldn't justify burning another week's usage just to
attempt reproduction. So the follow-up test below is the closest controlled
substitute I could run without maxing my usage a second time: isolating
"long idle period + app restart" as a variable on its own, separate from the
usage-limit wait specifically.

Follow-up test: full power-down
I fully powered down the machine (not just closed the app) and restarted,
then reopened this same conversation.

Result: CLAUDE_CODE_SESSION_ID was IDENTICAL before and after the reboot
(e510f0f6-4b02-4aee-ae2d-59327cbdba0a both times) — so this is not a case of
the harness assigning a new session to a continued conversation, as I'd
originally assumed.

However, the session's scratchpad directory under /private/tmp was completely
empty after the restart, with a fresh directory timestamp matching the reboot
time. So the actual bug is more specific than my original report suggested:

The local scratch/sandbox directory does not survive a full OS reboot (and
possibly not a long idle/usage-limit wait either, per the original report),
even when Claude Code correctly recognizes the returning session as the same
one. Session identity is preserved correctly; the working directory contents
are not. Any in-progress local files a user hasn't manually copied elsewhere
are silently lost, with no warning to the user or the model that this will
happen.

This suggests the fix belongs in how the session's scratch directory is
provisioned/restored on resume, not in session-ID assignment logic, which
appears to be working correctly. If it turns out to be tied to how /private/tmp
is handled across reboots on Apple Silicon specifically, that would also
narrow the fix considerably.

saaranshM · 1 month ago

Not a fix for the sandbox bug itself, but I found a workaround that made my overnight runs much less painful.

Instead of coming back hours after the quota resets, I resume the same session ID as soon as the official usage limit lifts. I ended up automating that with unsnooze.

When a session stops because of a usage limit, it records the reset as an absolute timestamp and automatically runs claude --resume <session-id> the moment the limit expires. That cuts the idle window from "until I wake up" to just a minute or two, which has made long-running refactors much more reliable for me.

https://github.com/saaranshM/unsnooze

bcherny collaborator · 14 days ago

Thanks for the detailed write-up — this one is working as designed today, but your expectation is a fair one.

I checked on 2.1.233 (Linux) and couldn't black-box reproduce it, because the behavior belongs to the cloud environment rather than the CLI: it needs a real web session plus a multi-day idle window.

What happened: cloud sessions stop after a period of inactivity and the environment is reclaimed. Reopening the session provisions a fresh environment with your conversation history restored — but not the filesystem. That's why the working directory came back under a new session ID and empty. This is documented under "Environment expired" here: https://code.claude.com/docs/en/claude-code-on-the-web

Where we agree with you: nothing in the conversation tells you (or Claude) that the environment was replaced, so the loss is only discovered mid-task and costs tokens to recover from. We're passing along three suggestions: show a clear notice on resume after an environment is reclaimed, say explicitly in the docs that only conversation history survives, and have Claude push or re-publish in-progress work before long idles.

In the meantime, the reliable way to carry work across a wait is to commit and push it to a branch — anything left only in the session's working directory is not durable.

🤖 Generated with Claude Code