Scheduled tasks sharing a due time: only the first 3 fire, the rest are silently dropped and left enabled with a past nextRunAt (Windows, 2.1.217)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
When several one-time scheduled tasks share the same fireAt, only the first three fire. The remainder are silently dropped — they stay enabled: true with nextRunAt frozen at the now-past due time, and are never retried. No error, no notification, no trace anywhere.
This is not a wake/sleep or connectivity failure: the machine was awake, the app was open and actively in use, and three sibling tasks fired normally in the same instant.
Environment
- Claude Code 2.1.217, Windows desktop app
- Windows 11 Pro 10.0.26200
- 6 one-time (
fireAt) tasks, all due 2026-07-30T22:05:00.000Z - Created by 6 parallel Claude Code sessions pausing at a usage-window reset, each scheduling its own resume
Evidence
Six tasks, identical fireAt. Exactly three fired, ~150 ms apart, then it stopped:
| # | taskId | fired | lastRunAt | enabled after |
|---|---|---|---|---|
| 1 | adr0114-push-pr | ✅ | 22:05:48.334Z | false (auto-disabled, correct) |
| 2 | resume-mefor-adr0076-pr84 | ✅ | 22:05:48.484Z | false (correct) |
| 3 | resume-maturity-posture-pr96 | ✅ | 22:05:48.641Z | false (correct) |
| 4 | resume-vault-salvage-survey | ❌ | absent | true, nextRunAt = 22:05:00.000Z |
| 5 | resume-adr-0154 | ❌ | absent | true, nextRunAt = 22:05:00.000Z |
| 6 | resume-engine-code-defects-pr | ❌ | absent | true, nextRunAt = 22:05:00.000Z |
The split follows creation order exactly. SKILL.md mtimes (epoch): 1785448375, 1785448387, 1785448389 → fired; 1785448392, 1785448401, 1785448416 → dropped. The three oldest ran; the three newest did not. That ordering makes a concurrency cap of 3 with no queue and no retry the most likely mechanism — the overflow is discarded rather than deferred.
Verified still unfired 7+ minutes after the due time, with the app open and responsive. nextRunAt remains in the past and nothing re-evaluates it, so these tasks appear "scheduled" indefinitely while being permanently dead.
Expected
Either (a) all six run, queued behind the cap, or (b) the overflow retains a future nextRunAt and fires when a slot frees. Whichever is chosen, a task that was due and did not run must not be left enabled: true with a past nextRunAt and no record.
Actual
Three run. Three are dropped with no error surface, no notification, and a ledger state that is indistinguishable from "still scheduled."
Why this one is costly
The failure is silent and inverted: the ledger reports a healthy, enabled, scheduled task. The only way to discover it is to notice the work never happened. In this case each dropped task carried a self-contained resume prompt for a paused session — so a dropped fire means paused work is stranded with no signal.
It also concentrates precisely where it hurts: parallel sessions pausing at a shared usage-window reset all schedule for the same moment, so the tasks most likely to collide are exactly the ones created by this workflow. A round number like :05 makes collision the norm, not an edge case.
Reproduction
- Create 6 one-time tasks with the same
fireAta few minutes out (separate sessions, or sequentially in one). - Keep the app open and the machine awake.
- At the due moment, observe three fire ~150 ms apart.
list_scheduled_tasks: the other three showenabled: true,nextRunAtin the past, nolastRunAt. They never fire.
Related
- #76961 — local scheduled tasks: silent no-trace failures + missed-run ledger desync. Same class (silent drop, ledger desync) but macOS, ~37 tasks, cron cadences, and attributed to sleep/wake and connection-drop paths. This report is Windows, one-time
fireAt, machine awake, and has a sharper signature: a clean 3-fired/3-dropped split by creation order at a single instant, which points at a concurrency cap rather than a wake or transport failure. - #55631 — scheduler stops firing until restart.
- #72710 — one-time
fireAtnever fires (backing file never persisted). Distinct here: the backing files persisted fine and three siblings fired from the same batch.
Suggested fix
- Queue the overflow instead of discarding it — respect the cap, but drain it.
- Never leave
enabled: truewith anextRunAtin the past; that state is unreachable and reads as healthy. - Surface a dropped/skipped fire (notification or a
lastErroron the task) so silent loss is impossible.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗