Hmbown/CodeWhale · error
sub-agent task should finish
Error message
sub-agent task should finish
What it means
Panic from `.expect("sub-agent task should finish")` on the JoinHandle result: the outer timeout passed but the task itself returned Err (joined error / panicked inside the task). The task completed after the timeout interruption but failed instead of finishing cleanly.
Solutions
- Run with RUST_BACKTRACE=1 and read the inner task panic to find the failing point inside the sub-agent task
- Check that the retry-exhausted path returns Ok (finished status) rather than erroring
- Verify channels the task depends on are not closed/dropped before the final retry completes
Example fix
// before
.await.expect("sub-agent task must not park waiting for checkpoint input")
.expect("sub-agent task should finish");
// after
.await.unwrap_or_else(|_| panic!("task did not complete in time"))
.unwrap_or_else(|e| panic!("task finished with error: {e}")); Defensive patterns
Strategy: try-catch
Try / catch
match tokio::time::timeout(Duration::from_secs(5), task_handle).await {
Ok(Ok(())) => {},
Ok(Err(e)) => panic!("task errored: {e}"),
Err(_) => panic!("task timed out"),
} Prevention
- Return a typed terminal status instead of panicking inside spawned tasks
- Include the JoinError in assertion messages
- Avoid unwrap on channels near the retry-exhaustion boundary
When it happens
Trigger: task_handle resolves to Err because the spawned sub-agent task panicked or returned an error after exhausting timeout retries, e.g., unwrap on an expected channel/message that was consumed by the mailbox drain.
Common situations: Task panic on a closed channel after retries exhausted; assertion inside the task failing on the final attempt; JoinError from an aborted task.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- API timeout should publish an Interrupted mailbox lifecycle…
- first timed-out API attempt should reach the test server
- sub-agent task must not park waiting for checkpoint input
- Agent not found
- Agent not found
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/5d96c64d2f7a1cdb.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/tests.rs:9016
return (id, reason);
}
}
tokio::time::sleep(Duration::from_millis(10)).await;
}
})
.await
.expect("API timeout should publish an Interrupted mailbox lifecycle event");
assert_eq!(interrupted_envelope.0, agent_id);
assert!(
interrupted_envelope.1.contains("API call timed out"),
"reason should carry the timeout context: {}",
interrupted_envelope.1
);
tokio::time::timeout(Duration::from_secs(5), task_handle)
.await
.expect("sub-agent task must not park waiting for checkpoint input")
.expect("sub-agent task should finish");
assert_eq!(
calls.load(Ordering::SeqCst),
SUBAGENT_API_TIMEOUT_MAX_RETRIES.saturating_add(1) as usize,
"needs-input interruption must not park for continuation; the API call \
is retried up to the timeout-retry budget, then stops"
);
let interrupted = {
let manager = manager.read().await;
manager
.get_result(&agent_id)
.expect("agent should stay registered")
};
assert!(matches!(interrupted.status, SubAgentStatus::Interrupted(_)));
let checkpoint = interrupted
.checkpoint
.as_ref()
.expect("timeout should preserve checkpoint");View on GitHub (pinned to 433685b202)