Related issues
This looks like the same bug family as #852, #493, #513, and #624, but with a
different trigger than any of them — worth checking whether hasRunningSubagents()
(named in #852) also consults on-disk task state under ~/.claude/tasks/, not just
the in-memory activeAsyncSubagents/pendingAsyncSubagents maps that #493/#852
discuss.
Summary
Stop:Callback fired continuously for ~2.5 hours, blocking turn completion with:
Background subagents are still running. Use TaskOutput task_id="..." block=true
to wait for their results before ending your turn.
TaskList and TaskOutput(block=true) both confirmed zero live background tasks
throughout, on every attempt. The false signal survived a context-compaction event
and a full kill of the underlying OS process. Root cause traced to a stale,
unrelated task record left in in_progress state from a different project,
over three weeks earlier — the check behind Stop:Callback appears to treat "any
task anywhere under ~/.claude/tasks/ with status: in_progress" as "a subagent is
currently running," with no scoping to the current session, project, or actual live
process/task-ID state.
Environment
- Claudian (Obsidian plugin), engine version 2.1.209,
entrypoint: sdk-ts
- OS: Windows
- Session file:
faf39593-3157-448f-ad56-f34cc6e0ea84.jsonl
Timeline (UTC, from the session transcript)
- 16:29 — Grading workflow starts; coordinator launches 10 background
subagents via Agent(run_in_background: true).
- 16:51:53 — Stop hook fires once, correctly: "Background subagents are
still running." Claude calls TaskOutput for the two still-running agents
(Ormond, Thompson) as instructed. Resolves normally in a single turn — this
firing is not part of the later loop.
- 17:03:12 — Auto-compaction triggers (
preTokens: 189128) while 2 subagents
are still finishing.
- 17:08:21 → 17:22:43 — First loop burst: 30 consecutive identical
stop_hook_summary events, ~29s apart:
{"type":"system","subtype":"stop_hook_summary","hookCount":2,
"hookInfos":[{"command":"powershell ... stop-hook.ps1"},{"command":"callback"}],
"hookErrors":["Background subagents are still running. Use `TaskOutput task_id=\"...\" block=true` to wait for their results before ending your turn."]}
-
TaskList repeatedly returns "No tasks found"; direct inspection of the
coordinator process's live children shows none alive. False positive confirmed.
-
18:50:23 → 18:51:19 — Second, tighter burst: 13 firings in <1 minute
(~4.3s apart).
-
User kills the coordinator process (PID 64468). Claudian auto-relaunches a
new process (PID 50024), resumes the same session state — the stuck flag
returns immediately, proving it's not tied to the OS process or in-memory state.
-
Located ~/.claude/tasks/01253de0-dce6-4346-a798-89ca4b5f1b4a/1.json:
{
"id": "1",
"subject": "Complete HTML to Markdown conversion audit and repair",
"status": "in_progress",
...
}
Dated June 18 — over 3 weeks before this incident — from an unrelated
project (Roll20/D&D campaign markdown conversion, not the grading job in
question). An empty .lock file sits alongside it, also dated June 18.
-
Transcript ends here; user force-killed the process again shortly after to
break the loop for good.
Evidence ruling out user-configured hooks
~/.claude/settings.json registers exactly one Stop hook — a PowerShell toast
notifier (async: true), which never inspects task state and cannot inject
blocking feedback. Its text never matches the repeating error. Verified
independently across the whole incident.
Impact
- ~2.5 hours of session time consumed across two hard loop bursts
- Not resolvable from within the session — no tool exposes which task record is responsible; required manual filesystem digging under
~/.claude/tasks/
- Survives context compaction
- Survives killing and relaunching the process
- Will recur on any future session, any project, for as long as any stale
in_progress task record exists anywhere in ~/.claude/tasks/
Suggested fixes
- Scope whatever
hasRunningSubagents() (or its on-disk equivalent) checks to
the current session/project, not any in_progress record anywhere on disk.
- Add a staleness/TTL check — a task untouched for weeks shouldn't count as
"currently running."
- Have the hook's error text include the actual task/agent ID it thinks is
running (currently a literal "..." placeholder), so users can self-diagnose
instead of manually searching ~/.claude/tasks/.
- Since killing+relaunching the process didn't clear it, whatever persists this
flag should be reset on relaunch, or at least be clearable via a slash command.
Workaround applied
Manually edited ~/.claude/tasks/01253de0-dce6-4346-a798-89ca4b5f1b4a/1.json,
setting status from in_progress to completed.
Related issues
This looks like the same bug family as #852, #493, #513, and #624, but with a
different trigger than any of them — worth checking whether
hasRunningSubagents()(named in #852) also consults on-disk task state under
~/.claude/tasks/, not justthe in-memory
activeAsyncSubagents/pendingAsyncSubagentsmaps that #493/#852discuss.
activeAsyncSubagents, same session, Skill→Agent nesting.hasRunning = true, or foregroundagents lingering in the in-memory maps.
cross-project task record is enough on its own, in a brand new session.
Summary
Stop:Callbackfired continuously for ~2.5 hours, blocking turn completion with:TaskListandTaskOutput(block=true)both confirmed zero live background tasksthroughout, on every attempt. The false signal survived a context-compaction event
and a full kill of the underlying OS process. Root cause traced to a stale,
unrelated task record left in
in_progressstate from a different project,over three weeks earlier — the check behind
Stop:Callbackappears to treat "anytask anywhere under
~/.claude/tasks/withstatus: in_progress" as "a subagent iscurrently running," with no scoping to the current session, project, or actual live
process/task-ID state.
Environment
entrypoint: sdk-tsfaf39593-3157-448f-ad56-f34cc6e0ea84.jsonlTimeline (UTC, from the session transcript)
subagents via
Agent(run_in_background: true).still running." Claude calls
TaskOutputfor the two still-running agents(Ormond, Thompson) as instructed. Resolves normally in a single turn — this
firing is not part of the later loop.
preTokens: 189128) while 2 subagentsare still finishing.
stop_hook_summaryevents, ~29s apart:{"type":"system","subtype":"stop_hook_summary","hookCount":2, "hookInfos":[{"command":"powershell ... stop-hook.ps1"},{"command":"callback"}], "hookErrors":["Background subagents are still running. Use `TaskOutput task_id=\"...\" block=true` to wait for their results before ending your turn."]}TaskListrepeatedly returns "No tasks found"; direct inspection of thecoordinator process's live children shows none alive. False positive confirmed.
18:50:23 → 18:51:19 — Second, tighter burst: 13 firings in <1 minute
(~4.3s apart).
User kills the coordinator process (PID 64468). Claudian auto-relaunches a
new process (PID 50024), resumes the same session state — the stuck flag
returns immediately, proving it's not tied to the OS process or in-memory state.
Located
~/.claude/tasks/01253de0-dce6-4346-a798-89ca4b5f1b4a/1.json:{ "id": "1", "subject": "Complete HTML to Markdown conversion audit and repair", "status": "in_progress", ... }Dated June 18 — over 3 weeks before this incident — from an unrelated
project (Roll20/D&D campaign markdown conversion, not the grading job in
question). An empty
.lockfile sits alongside it, also dated June 18.Transcript ends here; user force-killed the process again shortly after to
break the loop for good.
Evidence ruling out user-configured hooks
~/.claude/settings.jsonregisters exactly oneStophook — a PowerShell toastnotifier (
async: true), which never inspects task state and cannot injectblocking feedback. Its text never matches the repeating error. Verified
independently across the whole incident.
Impact
~/.claude/tasks/in_progresstask record exists anywhere in~/.claude/tasks/Suggested fixes
hasRunningSubagents()(or its on-disk equivalent) checks tothe current session/project, not any
in_progressrecord anywhere on disk."currently running."
running (currently a literal
"..."placeholder), so users can self-diagnoseinstead of manually searching
~/.claude/tasks/.flag should be reset on relaunch, or at least be clearable via a slash command.
Workaround applied
Manually edited
~/.claude/tasks/01253de0-dce6-4346-a798-89ca4b5f1b4a/1.json,setting
statusfromin_progresstocompleted.