Hmbown/CodeWhale · error
Agent not found
Error message
Agent {agent_id} not found What it means
cancel_agent first resolves the caller-supplied agent reference to an agent ID, then looks the ID up in the in-memory agent map. If no live (tracked) agent matches, the cancel cannot proceed and the library throws this not-found error, naming the resolved agent_id.
Solutions
- List the currently tracked agents first and cancel using a ref from that list.
- Check whether the agent already finished; a completed agent needs no cancellation.
- Re-run the sub-agent spawn if the intent was to restart it, then cancel the new ref.
- Verify the ref/ID spelling and that you are in the same session that spawned the agent.
Example fix
// before: cancelling a possibly-finished agent blindly
manager.cancel_agent("agent-7")?;
// after: check liveness first
if manager.list_agents().iter().any(|a| a.id == "agent-7") {
manager.cancel_agent("agent-7")?;
} Defensive patterns
Strategy: validation
Validate before calling
fn can_cancel(mgr: &SubAgentManager, agent_ref: &str) -> bool {
mgr.resolve_agent_ref(agent_ref).ok()
.map(|id| mgr.find_agent(&id).is_some())
.unwrap_or(false)
} Type guard
fn live_agent<'a>(mgr: &'a SubAgentManager, agent_ref: &str) -> Option<&'a SubAgent> {
let id = mgr.resolve_agent_ref(agent_ref).ok()?;
mgr.find_agent(&id)
} Try / catch
match manager.cancel_agent(agent_ref) {
Err(e) if e.to_string().contains("not found") => info!("agent already finished"),
r => r?,
} Prevention
- Always cancel using refs obtained from the current session's list of live agents.
- Skip cancellation for agents already reported terminal.
- Do not persist and reuse agent refs across session restarts.
When it happens
Trigger: Calling cancel_agent(ref) with a reference to an agent that has already terminated and been reaped, was never spawned in this session, or whose ID was mistyped/aliased.
Common situations: Cancelling after the sub-agent already completed and its record was cleared; using an agent ref from a previous session after state restore; a stale UI handle to a finished agent.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Agent not found in the active session
- Cannot queue a parent message for agent
- parent turn is already settling foreground work as
- session was deleted
- agent action=claim widens an enforced write scope, and the…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/d3df5d51f5845ffe.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:5671
.checkpoint
.as_ref()
.is_some_and(|checkpoint| checkpoint.parked_at_turn_end);
match &result.status {
SubAgentStatus::Failed(err) => record.error = Some(err.clone()),
SubAgentStatus::BudgetExhausted => record.error = message.clone(),
_ => {}
}
}
self.record_worker_event(worker_id, status, message, Some(result.steps_taken), None);
}
pub fn cancel_agent(&mut self, agent_ref: &str) -> Result<SubAgentResult> {
let agent_id = self.resolve_agent_ref(agent_ref)?;
let mut terminal = {
let agent = self
.agents
.get(&agent_id)
.ok_or_else(|| anyhow!("Agent {agent_id} not found"))?;
if agent.status != SubAgentStatus::Running {
let snapshot = self.snapshot_for_listing(agent);
return Ok(self.terminalize_settled_worker_on_cancel(&agent_id, snapshot));
}
if agent.completion_claimed {
// Still running, with its terminal transition already claimed:
// mid-flight, not settled. Stealing it here would record a
// second terminal outcome for one child.
return Ok(self.snapshot_for_listing(agent));
}
self.snapshot_for_listing(agent)
};
terminal.status = SubAgentStatus::Cancelled;
terminal.result = Some("Cancelled by parent request.".to_string());
terminal.needs_input = None;
if !self.finish_terminal_result(&agent_id, terminal, true, true) {
return self.get_result(&agent_id);
}View on GitHub (pinned to 73e0f67d83)