{"record":{"id":"7c8a101f0faa74c4","repo":"Hmbown/CodeWhale","slug":"task-not-found-task-id","errorCode":null,"errorMessage":"Task not found: {task_id}","messagePattern":"Task not found: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/task_manager.rs","lineNumber":1423,"sourceCode":"        id_or_prefix: &str,\n        owner_session_id: &str,\n    ) -> Result<TaskRecord> {\n        self.get_task_visible_to(id_or_prefix, Some(owner_session_id))\n            .await\n    }\n\n    /// Retrieve the exact owned task stamped onto a trusted runtime thread.\n    ///\n    /// The runtime thread supplies a full durable id rather than model input.\n    /// Legacy ownerless tasks fail closed even when restored as active.\n    pub(crate) async fn get_task_for_active_runtime(&self, task_id: &str) -> Result<TaskRecord> {\n        let state = self.state.lock().await;\n        state\n            .tasks\n            .get(task_id)\n            .filter(|task| task.owner_session_id.is_some())\n            .cloned()\n            .ok_or_else(|| anyhow!(\"Task not found: {task_id}\"))\n    }\n\n    async fn get_task_visible_to(\n        &self,\n        id_or_prefix: &str,\n        owner_session_id: Option<&str>,\n    ) -> Result<TaskRecord> {\n        let state = self.state.lock().await;\n        let id = resolve_task_id_visible_to(&state.tasks, id_or_prefix, owner_session_id)?;\n        state\n            .tasks\n            .get(&id)\n            .cloned()\n            .ok_or_else(|| anyhow!(\"Task not found: {id_or_prefix}\"))\n    }\n\n    /// Cancel a queued or running task by id/prefix.\n    pub async fn cancel_task(&self, id_or_prefix: &str) -> Result<TaskCancellation> {","sourceCodeStart":1405,"sourceCodeEnd":1441,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/task_manager.rs#L1405-L1441","documentation":"TaskManager::get_task_for_active_runtime looks up a task by its full durable id, stamped onto a trusted runtime thread rather than model input. The lookup fails closed in two cases: the id is absent from the task map, or the record has owner_session_id == None (a legacy ownerless task). So even a restored, active task without an owner is rejected.","triggerScenarios":"A runtime thread references a task id that was pruned, belongs to a rotated store, or predates owner tracking (owner_session_id is None). Passing a prefix is not supported here — only exact ids resolve.","commonSituations":"Upgrading from an older version whose persisted task records lack owner_session_id; session restore picking up legacy active tasks; referencing a task id after its record was garbage-collected.","solutions":["Use the exact task id returned by the enqueue/creation call in the same session — not a prefix or an id from a prior session.","If the record is legacy (no owner), re-create the task so it is stamped with the current session id.","Check the task still exists via a list/counts call before the runtime thread dereferences it.","Migrate old task records to backfill owner_session_id if legacy data must stay usable."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate before use: task must exist and carry an owner session id.\nlet state = task_manager.snapshot().await;\nlet ok = state.tasks.get(&task_id)\n    .is_some_and(|t| t.owner_session_id.is_some());\nanyhow::ensure!(ok, \"task {task_id} missing or legacy ownerless; re-create it\");\nlet task = task_manager.get_task_for_active_runtime(&task_id).await?;","typeGuard":null,"tryCatchPattern":"match task_manager.get_task_for_active_runtime(&id).await {\n    Ok(task) => task,\n    Err(e) if e.to_string().contains(\"Task not found\") => {\n        // fail closed: re-enqueue the work instead of retrying the stale id\n        reenqueue_work().await?\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Thread the exact durable id from creation into runtime threads — never reconstruct or truncate it.","Re-create legacy ownerless tasks after upgrading instead of reusing them.","Treat 'Task not found' on this path as terminal for that id; do not loop on it."],"tags":["tasks","task-manager","not-found","ownership"],"backgroundTag":"entity-not-found","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}