[Bug] Background sub-agent output files empty (0 bytes) on Windows
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [ ] I am using the latest version of Claude Code
What's Wrong?
When launching background sub-agents via the Agent tool with run_in_background: true, the completed task frequently displays "0 tokens" in
the status line despite the agent having executed many tool calls and produced significant output.
Example:
├─ superpowers:code-reviewer (Review code quality) · 58 tool uses · 0 tokens ⎿ Done
├─ Agent (Review UI/UX design) · 34 tool uses · 0 tokens ⎿ Done
What Should Happen?
Should display actual token count, e.g.:
├─ superpowers:code-reviewer (Review code quality) · 58 tool uses · 41397 tokens ⎿ Done
Error Messages/Logs
No error messages. The issue is silent - output files are empty but no errors are logged.
Steps to Reproduce
- Launch multiple background sub-agents with run_in_background: true
Agent
({
subagent_type: "superpowers:code-reviewer",
description: "Review code",
prompt: "...",
run_in_background: true
})
- Wait for agents to complete
- Observe the status line showing "X tool uses · 0 tokens"
- Check task output files in temp directory - most are empty (0 bytes)
Evidence from my session:
- Total output files: 89
- Empty files: 82 (92%)
- Non-empty files: 7 (8%)
Claude Model
Other
Is this a regression?
I don't know
Last Working Version
N/A
Claude Code Version
2.1.80 (Claude Code)
Platform
Other
Operating System
Windows
Terminal/Shell
VS Code integrated terminal
Additional Information
Root Cause Analysis:
After investigating the task output files, I identified a race condition:
Timeline:
T0: Sub-agent completes (e.g., 41397 tokens generated)
T1: completeAgentTask() called
T2: void evictTaskOutput(taskId) ← FIRE-AND-FORGET (doesn't wait!)
T3: enqueueAgentNotification() sends notification immediately
T4: Main session receives notification and reads output file
T5: Disk flush finally completes (too late!)
Result: File is empty at T4 → displays "0 tokens"
The evictTaskOutput() function awaits flush, but the caller uses void evictTaskOutput(taskId) (fire-and-forget). The notification is sent
before disk write completes.
Suggested Fix:
export async function completeAgentTask(result, setAppState): Promise<void> {
// ...update state...
await evictTaskOutput(taskId) // Wait for flush before notifying
}
Note: I'm unable to upgrade to 2.1.126 due to third-party API compatibility, but this race condition is likely still present as it's a
fundamental async/await issue.
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗