{"record":{"id":"5a23334c90346cbb","repo":"Hmbown/CodeWhale","slug":"task-not-found-id-or-prefix","errorCode":null,"errorMessage":"Task not found: {id_or_prefix}","messagePattern":"Task not found: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/task_manager.rs","lineNumber":2445,"sourceCode":"    id_or_prefix: &str,\n    owner_session_id: Option<&str>,\n) -> Result<String> {\n    let visible = |record: &TaskRecord| {\n        owner_session_id.is_none_or(|owner_session_id| {\n            record.owner_session_id.as_deref() == Some(owner_session_id)\n        })\n    };\n    if tasks.get(id_or_prefix).is_some_and(visible) {\n        return Ok(id_or_prefix.to_string());\n    }\n    let matches = tasks\n        .iter()\n        .filter(|(id, record)| id.starts_with(id_or_prefix) && visible(record))\n        .map(|(id, _)| id)\n        .cloned()\n        .collect::<Vec<_>>();\n    match matches.len() {\n        0 => bail!(\"Task not found: {id_or_prefix}\"),\n        1 => Ok(matches[0].clone()),\n        _ => bail!(\n            \"Ambiguous task prefix '{}': matches {} tasks\",\n            id_or_prefix,\n            matches.len()\n        ),\n    }\n}\n\nfn resolve_task_id(tasks: &HashMap<String, TaskRecord>, id_or_prefix: &str) -> Result<String> {\n    resolve_task_id_visible_to(tasks, id_or_prefix, None)\n}\n\nfn summarize_json(value: &Value) -> Option<String> {\n    let text = serde_json::to_string(value).ok()?;\n    Some(summarize_text(&text, TIMELINE_SUMMARY_LIMIT))\n}\n","sourceCodeStart":2427,"sourceCodeEnd":2463,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/task_manager.rs#L2427-L2463","documentation":"Task id resolution: the argument matched neither a full visible task id nor the prefix of any visible task. Resolution first tries an exact key lookup, then prefix matching over ids, optionally filtered by a visibility predicate; zero matches out of both paths produces this error.","triggerScenarios":"Calling a task-scoped API (status, update, result) with a mistyped id, a stale id from a previous run, a too-short prefix that no longer matches, or an id that exists but is filtered out by the caller's visibility scope.","commonSituations":"Typing a prefix in a command or tool call; referencing a task from an old session whose files were archived; scope filters (e.g. 'my tasks') hiding the target; ids copied after truncation in a narrow UI.","solutions":["List tasks (list_tasks / the task list view) and copy the full id or a longer prefix from the current store.","If you scoped the lookup (resolve_task_id_visible_to with a filter), widen the scope or confirm the task is visible to the calling context.","Prefixes only need to be unambiguous, not complete: 4-6 hex chars usually suffice; if you get 'Ambiguous task prefix' instead, add characters."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify a reference resolves before acting on it:\nfn task_exists(tasks: &HashMap<String, TaskRecord>, prefix: &str) -> bool {\n    tasks.get(prefix).is_some() || tasks.keys().any(|id| id.starts_with(prefix))\n}","typeGuard":null,"tryCatchPattern":"match resolve_task_id(&tasks, &arg) {\n    Ok(id) => act_on(id).await,\n    Err(e) if e.to_string().starts_with(\"Task not found\") => {\n        let options = tm.list_tasks(Some(10)).await;\n        show_picker(options).await // recover by reselecting\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Resolve ids once at input time and carry the full id through the call chain.","When surfacing task ids, display the full 21-char form or a clearly truncated one with copy support.","Remember visibility filters: a hidden task is 'not found' even though its file exists."],"tags":["task","lookup","not-found","rust"],"backgroundTag":"entity-not-found","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}