Hmbown/CodeWhale · error · anyhow::Error
Task not found: {id}
Error message
Task not found: {id} What it means
In the cancel path, resolve_task_id_visible_to already returned a full id computed from the same locked state.tasks map, and get_mut(&id) then failed. Because both lookups run under the same mutex on the same map, this branch is a defensive invariant guard, not an expected outcome: it would only fire if the resolver and the map disagreed (internal state corruption). Users should never see it under normal operation.
Source
Thrown at crates/tui/src/task_manager.rs:1480
self.get_task_for_active_runtime(task_id).await?;
self.cancel_task(task_id).await
}
async fn cancel_task_visible_to(
&self,
id_or_prefix: &str,
owner_session_id: Option<&str>,
) -> Result<TaskCancellation> {
let mut state = self.state.lock().await;
let id = resolve_task_id_visible_to(&state.tasks, id_or_prefix, owner_session_id)?;
let now = Utc::now();
let mut cancel_running = false;
let disposition = {
let task = state
.tasks
.get_mut(&id)
.ok_or_else(|| anyhow!("Task not found: {id}"))?;
match task.status {
TaskStatus::Queued => {
task.status = TaskStatus::Canceled;
task.lifecycle_seq = task.lifecycle_seq.saturating_add(1);
task.ended_at = Some(now);
task.duration_ms = Some(0);
push_timeline_entry(
task,
TaskTimelineEntry {
timestamp: now,
kind: "canceled".to_string(),
summary: "Task canceled before execution".to_string(),
detail_path: None,
},
);
state.queue.retain(|queued_id| queued_id != &id);
TaskCancelDisposition::Forced
}View on GitHub (pinned to 0c42157ee5)
Solutions
- Treat it as an internal invariant failure: capture logs and the persisted task state file.
- Restart the session; if it reproduces, inspect the persisted tasks store for corruption.
- Report it upstream with the cancel request's id_or_prefix and the task list.
Defensive patterns
Strategy: try-catch
Try / catch
let cancellation = match task_manager.cancel_task_visible_to(prefix, Some(session)).await {
Ok(c) => c,
Err(e) if e.to_string().contains("Task not found") => {
// invariant guard: resolver just resolved this id under the same lock.
// Log and surface as an internal error; do not blind-retry.
tracing::error!("cancel invariant violation: {e:#}");
return Err(e);
}
Err(e) => return Err(e),
}; Prevention
- Log the exact id_or_prefix and a task-list snapshot if this ever fires — it indicates internal state corruption.
- Keep persisted task state from being edited by hand; corrupted stores make invariant guards reachable.
When it happens
Trigger: Effectively unreachable through public APIs: it requires the task map to change between resolve_task_id_visible_to and get_mut while state is locked, e.g. memory corruption or a logic bug where the resolver returns an id not present in the map.
Common situations: If observed at all, it indicates a bug in TaskManager or corrupted persisted task state loaded at startup.
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
- Task not found: {task_id}
- hunt_verdict task update must be a string
- No saved sessions found for workspace {}.
- No saved sessions found.
- MCP server '{name}' not found
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/3fb2a7946259f549.
Report an issue: GitHub.