Hmbown/CodeWhale · error
cancel wins race
Error message
cancel wins race
What it means
Test panic: `manager.cancel_agent(&agent_id)` returned Err, failing `.expect("cancel wins race")`. The cancel path must win races against late completions, so an Err means the manager refused or failed to cancel a registered, running worker.
Solutions
- Confirm the agent's status allows cancellation at the call site (not already terminal).
- Check `input_tx` is still open if cancel signals via the input channel.
- Read the Err payload to distinguish unknown-agent from state-conflict refusals.
Example fix
// before
manager.cancel_agent(&agent_id).expect("cancel wins race");
// after
manager.cancel_agent(&agent_id)
.unwrap_or_else(|e| panic!("cancel wins race: {e:#}")); Defensive patterns
Strategy: try-catch
Validate before calling
let cancelable = manager.agents.get(&agent_id)
.map(|a| !matches!(a.status, SubAgentStatus::Cancelled | SubAgentStatus::Completed))
.unwrap_or(false);
assert!(cancelable, "agent must exist and be non-terminal to cancel"); Try / catch
manager.cancel_agent(&agent_id)
.unwrap_or_else(|e| panic!("cancel failed for {agent_id}: {e:#}")); Prevention
- Keep input_tx alive while the agent can be cancelled
- Only reject cancel for unknown agents, never for state the manager controls
- Test cancel-against-late-completion races whenever the result path changes
When it happens
Trigger: Calling `cancel_agent` on an agent inserted into `manager.agents` with a registered worker spec, when the cancel path requires a state (e.g. Running) the agent does not have, or its input channel is closed.
Common situations: Regression where cancel requires a live input_tx sender but the test's receiver was dropped; terminal-state guard rejecting an agent already in a terminal status.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- cancelled snapshot exists
- terminal snapshot remains
- parent interruption fan-in
- parent turn is already settling foreground work as
- read-only roles may revise their private working notes
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ac16a914698d3ed0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/tests.rs:6795
let mut manager = SubAgentManager::new(tmp.path().to_path_buf(), 2);
let agent_id = "agent_cancel_completion_race".to_string();
let (input_tx, _input_rx) = mpsc::unbounded_channel();
let agent = SubAgent::new(
agent_id.clone(),
FleetRole::Worker,
"race".to_string(),
make_assignment(),
"deepseek-v4-flash".to_string(),
None,
None,
input_tx,
tmp.path().to_path_buf(),
manager.current_session_boot_id.clone(),
);
manager.agents.insert(agent_id.clone(), agent);
manager.register_worker(make_worker_spec(&agent_id, tmp.path().to_path_buf()));
manager.cancel_agent(&agent_id).expect("cancel wins race");
let mut late = manager
.get_result(&agent_id)
.expect("cancelled snapshot exists");
late.status = SubAgentStatus::Completed;
late.result = Some("late success".to_string());
assert!(
!manager.update_from_result(&agent_id, late),
"late completion must lose the terminal transition"
);
let snapshot = manager
.get_result(&agent_id)
.expect("terminal snapshot remains");
assert_eq!(snapshot.status, SubAgentStatus::Cancelled);
assert_eq!(
snapshot.result.as_deref(),
Some("Cancelled by parent request.")
);View on GitHub (pinned to 73e0f67d83)