[BUG] Remote VM session: tool call in flight at laptop sleep phantom-denies after exactly 600s — "user doesn't want to take this action" + toolUseResult "Error: undefined", despite bypassPermissions

Open 💬 1 comment Opened Jun 12, 2026 by grepfruit

Summary

Claude Desktop (macOS) attached to Claude Code sessions running on a remote Linux VM. When the laptop lid closes while a session has a tool call in flight, that tool call hangs for exactly 600 s and then resolves to a phantom rejection:

The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed.

with is_error: true and toolUseResult: "Error: undefined". The model obeys the STOP and ends the turn, so every actively-working session silently dies ~10 minutes after the lid closes — all of them at once when several sessions are mid-turn. No prompt was ever shown, nothing was rejected by the user, and the affected tools (Read, Edit, Write, MCP calls) were all covered by "defaultMode": "bypassPermissions" and explicit permissions.allow rules.

This is the same defect previously reported in #65934 (there via VS Code code serve-web; same 600 000 ms timeout to the millisecond, same string, same toolUseResult: "Error: undefined"). #65934 was auto-closed as a duplicate of #35005, but #35005 is a different bug — see "Mis-dedup" below. As far as I can tell this defect is currently untracked.

Environment

  • Client: Claude Desktop for macOS 1.12603.1 (3df4fd, 2026-06-11 build); disconnect trigger = laptop lid close (sleep)
  • Remote: Linux VM (GCP, kernel 6.8.0-1060-gcp); Desktop remote runner under ~/.claude/remote/run/<id>/rpc.sock, session processes launched from ~/.claude/remote/ccd-cli/2.1.170; standalone CLI on the VM is 2.1.174
  • Permissions: "defaultMode": "bypassPermissions" in ~/.claude/settings.json, plus a broad permissions.allow list that includes bare Read, Edit, Write
  • Hooks: PreToolUse on Bash (dcg) and on AskUserQuestion only — neither matches the denied tools, and both emit their own distinct deny strings (verified; see "Ruled out")

Evidence

1. Every denial is exactly tool_use + 600.0 s

Sweep of all session transcripts on the VM (~/.claude/projects/*/*.jsonl): 25+ denial events across 19 sessions on 7 distinct days (2026-06-03 → 2026-06-12), every single one exactly 600.0xx s after its tool_use. Representative sample (UTC):

| Date | tool_use ts | deny ts | Δ | Tool | Session |
|---|---|---|---|---|---|
| Jun 12 | 07:59:16.073 | 08:09:16.089 | 600.016 s | Read (file in cwd) | e9891c6a |
| Jun 12 | 07:59:20.077 | 08:09:20.088 | 600.011 s | Read (file in cwd) | f34501a1 |
| Jun 11 | 16:04:53.454 | 16:14:53.488 | 600.034 s | Edit | 242fe0ab |
| Jun 11 | 16:07:11.886 | 16:17:11.900 | 600.014 s | Read | f08b6dfb |
| Jun 11 | 16:38:54.847 | 16:48:54.858 | 600.011 s | MCP (Linear save_comment) | a0a16a48 |
| Jun 10 | 12:44:51.157 | 12:54:51.184 | 600.027 s | Read | 9163f00d |
| Jun 09 | 16:22:05.772 | 16:32:05.786 | 600.014 s | Read | cab1b95f |
| Jun 08 | 06:55:17.834 | 07:05:17.846 | 600.012 s | Read | 3421ecc2 |

600.011–600.034 s, never less, never more — i.e. a 600 000 ms default timeout, not a human.

2. One lid close kills all mid-turn sessions in the same minute

  • Jun 12 07:59 → two sessions denied at 08:09:16 / 08:09:20
  • Jun 11 ~16:0x → three sessions denied 16:14–16:48
  • Jun 10 12:43–44 → two sessions denied 12:53–12:54
  • Jun 09 16:22 → two sessions, Jun 08 06:55 → two sessions (one had 3 parallel reads in flight; all three denied at +600 s each)

Sessions idle at lid close are unaffected. Only in-flight tool calls die.

3. Parallel in-flight calls deny serially at +10/+20/+30/+40 min

One session (Jun 04) had 4 tool calls in flight at 16:43:38–43. They denied at 16:53:38, 17:03:38, 17:13:38, 17:23:38 — one 600 s timeout at a time, queued.

4. Runner logs show the disconnect inside each window

~/.claude/remote/run/<id>/remote-server.log:

2026/06/12 08:08:17 [Server] Connection closed: @          ← inside the 07:59:16 → 08:09:16 window
2026/06/10 12:52:03 [Server] Connection closed: @
2026/06/10 12:52:03 [Server] writeResponse: wrote 0/49 bytes, error=write unix .../rpc.sock->@: use of closed network connection
2026/06/10 12:52:03 [Server] Failed to write response: ...  ← denials land 12:53:07 / 12:54:51

5. The injected string is the abort constant, not the user-reject string

In the native CLI binary (2.1.174) the string is defined inline next to the interrupt strings:

DHH="[Request interrupted by user]",
Yk="[Request interrupted by user for tool use]",
J3H="The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed."

So a timed-out/unanswerable permission request is surfaced to the model as an explicit user refusal — which the model rightly obeys, ending the turn. (The genuine user-reject string — "The user doesn't want to proceed with this tool use. The tool use was rejected…" — is a different constant.)

6. Ruled out

  • User hooks: PreToolUse hooks exist only for Bash (dcg — emits a verbose BLOCKED by dcg … Rule: … JSON deny, instantly) and AskUserQuestion (custom deny reason). Denied tools were Read/Edit/Write/MCP; no hook matches them and neither hook's message resembles the observed string.
  • Real user action: denials occur while the laptop is asleep, at exactly +600.0 s, simultaneously across sessions; genuine interrupts inject [Request interrupted by user …] instead.
  • Permission config: every denied call was covered by both bypassPermissions and an explicit permissions.allow rule — they should never round-trip to the client at all.

Steps to reproduce

  1. macOS Claude Desktop, session running on a remote VM, defaultMode: bypassPermissions.
  2. Give the session a long task so tool calls are continuously in flight.
  3. Close the laptop lid while a tool call is executing.
  4. Wait ≥ 10 minutes, reopen.
  5. The session has stopped; the in-flight tool call shows the phantom denial exactly 600 s after issue, toolUseResult: "Error: undefined".

Expected behavior

  1. Tools covered by bypassPermissions / permissions.allow should not require a client round-trip at all.
  2. A pending permission/ack request whose responder disconnected should pause and re-issue on reconnect — session survival across sleep was already fixed (changelog v2.1.71, "bridge session reconnection … within seconds after laptop wake"); the in-flight request pending at the moment of disconnect is the remaining gap.
  3. If it must fail, it should fail fast and with a distinct message ("permission request timed out — client disconnected"), not the user-refusal string the model is trained to obey. The current message also misleads users into auditing their hooks/guards for a denial that never happened.

Mis-dedup of #65934 — please don't repeat it

#65934 (same defect via code serve-web, exact same 600.0xx s timing and Error: undefined signature) was auto-closed as a duplicate of #35005. #35005 is a different 600 000 ms bug: the VS Code webview dropping a saved session ID on panel restore after 10 min idle. Same magic number, unrelated code path (session restore vs. in-flight permission round-trip). The dedup left this defect untracked.

Related

  • #65934 — same bug via VS Code code serve-web (closed as duplicate — incorrectly, see above)
  • #59171 — permission-IPC race killing sessions on macOS; reporter notes one failure mode fires even under bypassPermissions
  • #49790 — Desktop SSH-remote sessions should survive client disconnect
  • #31681 / changelog v2.1.71 — reconnect-after-wake fixed to seconds; consistent with what I observe on 2.1.174 (session survives, only the in-flight call dies)

Impact / workaround

Unattended long-running work on remote VMs — the headline use case for remote sessions — silently stops ~10 min after the client sleeps, with a message that blames the user. Recovery is trivial (any message resumes), but overnight/walk-away runs are lost time. Current workaround is tmux + headless CLI on the VM, bypassing the Desktop attach entirely.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗