Scheduled-task sessions intermittently freeze permanently on first/second tool call, never releasing their concurrency slot

Status Open
Reported on v2.1.258
Maintainer reply None cached
Activity 1 comment · opened Sep 7, 2026

Summary

Claude Code sessions launched by the local scheduled-tasks feature (mcp__scheduled-tasks__create_scheduled_task / the Cowork-style recurring routine) intermittently freeze permanently on their first or second tool call — the tool is invoked, no result is ever returned, and no further progress is made, indefinitely (confirmed up to 29+ hours before manual termination). This happens across different tool types (Bash, mcp__claude-in-chrome__navigate, mcp__claude-in-chrome__computer), so it does not appear to be specific to any one tool. The same machine's interactive Claude Code sessions, run over the same ~57-hour window, made hundreds of tool calls with zero hangs.

Because each frozen session never exits, it permanently occupies one of Claude Code's global concurrent-session slots. Over several days this accumulated enough frozen sessions to starve the scheduled-tasks feature's own dispatcher: other scheduled tasks were refused with reason: "global_limit" over 1,000 times in 24 hours, because the CLI-level concurrency cap had already been exhausted by sessions that had died in place days earlier and never freed their slot.

Environment

  • Claude Code version: 2.1.258 (also present on disk: 2.1.255)
  • OS: macOS 26.5.2 (build 25F84)
  • Invocation: local scheduled-tasks feature (not RemoteTrigger/cloud Routines)

Reproduction (observed, not yet minimized)

This was found via live investigation on a machine with several local scheduled tasks configured (daily/hourly automations doing a mix of local Bash work and claude-in-chrome browser automation). Exact repro steps to trigger it on demand are not yet known — it appears intermittent, not deterministic on every run — but it was reproduced multiple times over two consecutive nights (2026-09-06 and 2026-09-07) across five independent scheduled-task session launches.

Evidence

All timestamps UTC. Session IDs are the Claude Code session UUIDs (matching ~/.claude/projects/<project>/<uuid>.jsonl transcript filenames).

| Session ID | Scheduled task | Froze on | Timestamp last activity | Frozen for (when found) |
|---|---|---|---|---|
| f3217ecf-53b2-41e3-9a23-df3ac2193950 | agency-iq-shared-state-drift-check | Bash (python -m scripts.check_shared_state_drift) | 2026-09-06T18:20:13.004Z | ~29 hours (killed manually) |
| ad26099d-2315-43f6-bcf0-5aa27ed89a90 | claude-usage-daily-refresh | mcp__claude-in-chrome__navigate | 2026-09-06T18:19:34.326Z | ~29 hours (killed manually) |
| 427ac8da-5660-4cf5-9aee-bd145442bb84 | agency-iq-daily-health-sweep | Bash (health-sweep-preflight check) | 2026-09-07T23:13:46.042Z | still frozen at time of writing |
| 4c8aa374-a8dc-4a1c-8410-be2e82d17d60 | claude-usage-daily-refresh | mcp__claude-in-chrome__computer (screenshot) | 2026-09-07T23:14:11.779Z | still frozen at time of writing (got past one prior navigate call successfully) |
| 98dafdd3-9bee-4ceb-aaf6-5beb2c673cc1 | linkedin-nightly-triage | Bash (a curl login call to a localhost service) | 2026-09-07T23:13:58.499Z | still frozen at time of writing |

For each of these, the session transcript's final line is an assistant message containing a tool_use block. No corresponding tool_result was ever appended to the transcript, and process inspection (ps) confirmed the process was still running but its cumulative CPU time had stopped growing entirely (0.2–0.3s of CPU movement across independent 15-second samples, and zero growth across a persisted 2+ hour tracking window built specifically to confirm this).

Command line for one of the live-frozen sessions (4c8aa374), representative of the others:

claude --output-format stream-json --verbose --input-format stream-json --model default \
  --permission-prompt-tool stdio --allowedTools <long allowlist> \
  --setting-sources=user,project,local --permission-mode acceptEdits \
  --allow-dangerously-skip-permissions ...

Contrast: an interactive session on the same machine, running continuously from 2026-09-05T21:26Z through the time of writing (over 57 hours), made hundreds of successful tool calls (Bash, mcp__claude-in-chrome__*, file edits, etc.) with zero hangs of this kind.

What's been ruled out

  • Not slow MCP server startup. Each scheduled-task session spins up 8+ MCP server child processes (shadcn-ui-mcp-server, @playwright/mcp, @upstash/context7-mcp, @magicuidesign/mcp, figma-developer-mcp, analytics-mcp, mcp-search-console, plus a claude-mem plugin helper) via npm exec/uv tool uvx. Tested each of these standalone: all started in 3–10 seconds with warm local caches, no network-fetch delay.
  • Not the global concurrency cap itself (that's a separate, already-understood, and separately-reported behavior: scheduled-tasks.json's recordedSkips correctly records reason: "global_limit" refusals when the cap is saturated — that's a refusal to start, working as designed). This bug is about sessions that do start successfully and then never make progress or exit.
  • Not specific to browser automation. Two of the five confirmed cases froze on a plain local Bash command with no browser/network dependency at all (a Python drift-check script; a curl call to localhost).

Suspected mechanism (unconfirmed)

The frozen sessions' command line includes --permission-prompt-tool stdio. One hypothesis: if some tool call trips an internal permission/policy check (separate from the --permission-mode/--allowedTools flags passed at launch — several scheduled-task sessions on this machine carry an embedded autoMode policy JSON with soft_deny/ask categories) that decides to prompt for approval, and the scheduled-tasks launcher provides nothing to answer a stdio-based prompt (no human, no automated responder), the session would hang indefinitely waiting for a response that can structurally never arrive — rather than either proceeding (if truly bypassed) or failing cleanly with an error. This would explain why the hang is tool-agnostic (any tool call can trip a policy check) and specific to unattended dispatch (an interactive session has a human who can answer the prompt, or the classifier behaves differently when it detects an attached interactive session).

This is offered as a starting hypothesis for triage, not a confirmed root cause — we don't have visibility into Claude Code's internal policy/permission engine from outside the process.

Impact

  • Scheduled/background automations silently stop making progress with no error surfaced anywhere.
  • Each frozen session permanently holds a global concurrent-session slot, which compounds over days into full starvation of the scheduled-tasks feature for all other scheduled tasks on the machine (confirmed: one task refused 1,000+ times in 24h once several of these had accumulated).
  • Nothing in the product surfaces this failure mode to the user — it was only found via manual ps/transcript investigation.

Suggested mitigations (for consideration, not requesting these specifically)

  • A timeout on any tool call awaiting a permission response, with a clear failure (not an infinite hang) when no interactive responder is available in an unattended/scheduled-task context.
  • Surfacing "this scheduled task session appears stuck" somewhere the user would see it (a notification, or a field in scheduled-tasks.json distinguishing "started" from "made any progress since").

View original on GitHub ↗

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