[BUG] TaskList returns "No tasks found" after /compact while background tasks are still running and still addressable by ID

Status Open
Reported on v2.1.222
Maintainer reply None cached
Activity 0 comments · opened Aug 5, 2026

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?

After a /compact, TaskList returns No tasks found while a persistent Monitor spawned before the compaction is still running — visible in the user's session UI, and provably alive.

The proof is that the task is still fully addressable by ID. In the same post-compact turn where TaskList reported nothing:

TaskList  ->  "No tasks found"

TaskStop("bnzkx0ylm")
  ->  {"message":"Successfully stopped task: bnzkx0ylm (...)",
       "task_id":"bnzkx0ylm",
       "task_type":"local_bash",
       "command":"seen=\"\"\nwhile true; do\n  ...  sleep 30\ndone"}

TaskStop returned the full original command text of a monitor armed before the compaction. So the task record was intact and reachable the whole time — only the enumeration was empty. This is not the task being cleaned up; it is TaskList failing to see live tasks across a compaction boundary.

What Should Happen?

TaskList should enumerate every background task still running in the session, regardless of whether the tool result that created it has been summarized out of context. Enumeration is the only recovery path after a compaction — it is precisely when the assistant no longer has the IDs in context that it needs the list to be truthful.

Why this is worse than it looks

An empty TaskList does not read as "I lost the index." It reads as "there is no background work." The assistant's rational next move is therefore to re-arm the monitor it believes died — which is exactly what happened here:

  1. Pre-compact: a persistent Monitor polls two long-running jobs and notifies on completion.
  2. Post-compact: TaskList says No tasks found → assistant concludes the watch was lost → arms a second monitor on the same jobs.
  3. The user, who can still see both in the session UI, points out there are now two.

The duplicate is the mild outcome. The bad outcome is a task whose ID was never written down outside the context window: it stays running, invisible to TaskList, and cannot be stopped, because TaskStop needs the ID that only TaskList could have supplied. That is an unkillable orphan for the rest of the session.

There is also a silent-failure mode in the other direction: if the pre-compact monitor's notifications no longer route to the post-compact assistant, then an assistant that trusts TaskList and does nothing will wait forever for an event that will never arrive — with no signal distinguishing that from "still running."

Steps to Reproduce

  1. Arm a long-lived background task, e.g. Monitor with persistent: true running a poll loop.
  2. Confirm TaskList shows it.
  3. Run /compact.
  4. Call TaskListNo tasks found.
  5. Call TaskStop with the ID recorded from step 2 → succeeds, and echoes back the original command, confirming the task was alive and addressable in step 4.

Additional Information

  • Claude Code 2.1.222, macOS (darwin 25.5.0), zsh, model claude-opus-5.
  • Task type was local_bash (a Monitor), persistent: true.
  • Related but distinct: #77886 reports background agent handles becoming unreachable after summarization. Here the opposite holds — the handle is fully reachable, it is the enumeration that comes back empty. #77730 is also adjacent (IDs not resolving across a session-identity boundary). A fix that makes background-task enumeration survive compaction would likely cover the recovery path all three are missing.
  • Workaround in use: write background task IDs to a file before compacting, and after a compaction verify by ID rather than trusting TaskList.

View original on GitHub ↗