Scheduled-task sessions die unattended since ~2.1.220/221 (Windows): permission prompts + WarmLifecycle idle-disconnect orphan the run; frozen/unexited processes then pin scheduler concurrency slots
Scheduled-task sessions die unattended since ~2.1.220/221 (Windows): permission prompts + WarmLifecycle idle-disconnect orphan the run; frozen/unexited processes then pin scheduler concurrency slots
Environment
- Windows 11 Pro, build 10.0.26200 (desktop workstation, never sleeps: AC standby-timeout 0, zero Kernel-Power sleep/wake events in the System log across the failure period)
- Claude desktop app (Microsoft Store package, 1.28929.0.0) with desktop-managed scheduled tasks ("routines") — 18 tasks on daily/weekly crons, ~15 active
- claude-code CLI: regression first observed on 2.1.221 (first full day after auto-update from 2.1.219); persists through 2.1.222, 2.1.227, 2.1.229
- Sessions use local stdio MCP servers (Python/FastMCP) plus Bash-heavy workloads (git/gh/node)
Summary
Since the 2.1.219 → 2.1.221 update, scheduled-task sessions die when they run unattended. The same schedule ran cleanly for weeks before (12/12 clean completions on the last all-2.1.219 day). Root cause, established over 10 days of forensics on the app log, task store, transcripts, and process table:
- Scheduled runs now enforce interactive permission prompting per command (
Not auto-approving "Bash" in scheduled task "<task>": rule(s) not in stored approvals/no suggestions on request). Previously these same tasks executed unattended with zero stored approvals (15 of 18 tasks in the task store have none), so the permissive execution they relied on was removed by the update. - A session blocked on an unanswered prompt is idle.
WarmLifecycle— a new idle-timeout that first appears in the log on 2026-08-10 — disconnects idle sessions after 900 s and re-fires every 15 min ([WarmLifecycle:session] Idle timeout reached, disconnecting local_...). Once disconnected, the pending prompt is orphaned: the mobile app shows a stale "Approve once" card that no longer does anything, the desktop shows nothing actionable, and forwarded prompts expire to deny. - The process stays alive at ~0 CPU with the transcript frozen on a dangling
tool_use. These orphaned processes — and processes whose runs completed but never exited — keep counting against the scheduler's global concurrency limit (~2), producing continuousglobal_limit/per_task_limitskips (17,566 recorded in 10 days; one daily task logged 832 consecutive skips) and silently starving every other routine for days.
The net effect from the user's chair: routines "freeze" or "stop responding" only when nobody is at the machine, and mobile approval cards can't be acted on. It looks like suspension/power management; it is a permission model change plus an idle-disconnect that severs the prompt.
Timeline
| Date | Event |
|---|---|
| through Aug 6 | 2.1.219, weeks of clean scheduled runs (12 clean completions Aug 6) |
| Aug 6 | CLI auto-updated 2.1.219 → 2.1.221 |
| Aug 7 | First failures — three sessions die mid-run |
| Aug 10 | First WarmLifecycle idle-timeout entry ever in the app log |
| Aug 8–16 | 2.1.222 → 2.1.227 → 2.1.229; failure mode persists |
| Aug 13 | Confirmed: settings.json permissions.allow rules ARE honored by scheduled runs — a task with full allow coverage runs unattended, end-to-end, zero prompts |
| Aug 16 | With a project-level allowlist covering the studio's command vocabulary, all four daily routines completed unattended with zero prompts (first clean set since Aug 6) |
Observed failure signatures (all reproduced repeatedly)
- Spawn-time "wedge" — session emits its first tool call (an MCP tool), a permission request is emitted, nothing answers, session shows "running" for 13+ hours. Log proves the mechanism:
Emitted tool permission request … for mcp__<server>__pending_draftsat 09:39,Permission request … abortedonly when externally killed at 12:51. The same MCP server answers instantly from an interactive session concurrently. - Mid-run freeze — Bash call emitted deep in a run, uncovered by stored approvals, no answer,
WarmLifecycledisconnects at +15 min and every 15 min after; process alive at 0.02 s CPU/5 s; transcript silent for hours. A 95-min stall recovered once (someone touched the machine); 3 h+ never recovered. - Completed-but-unexited processes — run writes its final report, PR merged, and the process persists 25–36 h, still counted as running by the scheduler.
- Status is misleading both ways — "The session stopped responding" stamped ~5 min after a transcript ended cleanly with a merged PR (finalization race); externally killing an orphaned process reports "process exited with code 4294967295" as an error even when the run had delivered.
- Mobile approval is unreliable — Remote Control bridge flaps (repeated code-1006 closes and reconnects); combined with (2), the mobile approve buttons act on prompts that no longer exist.
Ruled out (with evidence)
- OS sleep/hibernate: event log clean, AC timeouts 0
- Token/usage budget: usage peaked at 10% of the 5-h window all week; no rate-limit events; skips are only
global_limit/per_task_limit - The MCP servers: instant responses from interactive sessions concurrently with the hang
- Power throttling / EcoQoS:
powercfg /powerthrottling disableon claude.exe changed nothing (retracted as a cause) - Machine resource pressure: reproduces with the machine otherwise idle
Confirmed diagnosis and working local remedy
- Cause: scheduled runs lost permissive execution → prompt on any uncovered command → idle →
WarmLifecycledisconnect orphans the prompt → run dies; dead/finished processes then hold scheduler slots. - Remedy that works: settings-file
permissions.allowrules (user-level for MCP tools, project-level.claude/settings.local.jsonwith ~90 Bash/Read/Edit rules covering the workload's vocabulary). With coverage complete, runs finish unattended with zero prompts. - Stopgap still needed: an external hourly watchdog (Task Scheduler + PowerShell) that kills routine processes idle >150 min or with zero tool results + a dangling tool call >45 min, to release the concurrency slots. Every reap paints a red error badge in the routines panel.
Asks
- Exempt sessions blocked on a permission prompt from
WarmLifecycleidle-disconnect, or make the pending prompt survive reconnection. This alone converts "silently dies" into "waits for the human" and is likely a small change. - Restore permissive execution for scheduled tasks or document the intended permission model for unattended runs (settings-file allowlists demonstrably work — say so, and surface a task's uncovered rules in the routines UI instead of a log line).
- Supervise scheduled-session child processes: detect frozen sessions, reap them, and release scheduler slots; exit the process when a scheduled run completes.
- Routines UI: distinguish "stale/reaped" from "run failed"; don't stamp "stopped responding" on runs whose transcripts completed; expire mobile approval cards whose prompts are gone.
- Stabilize the Remote Control bridge or make forwarded prompts idempotent across reconnects.
Condensed logs available on request: task-store skip records, watchdog log, WarmLifecycle disconnect series, and transcript tails showing the dangling tool calls.