{"record":{"id":"e6325035f6876a11","repo":"Hmbown/CodeWhale","slug":"unsupported-hunt-verdict-task-update-other-ex","errorCode":null,"errorMessage":"unsupported hunt_verdict task update '{other}'. Expected one of: hunting, hunted, wounded, escaped","messagePattern":"unsupported hunt_verdict task update '(.+?)'\\. Expected one of: hunting, hunted, wounded, escaped","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/task_manager.rs","lineNumber":2230,"sourceCode":"            &QueueFile {\n                queue: queue.iter().cloned().collect(),\n            },\n        )\n    }\n\n    fn persist_task_locked(&self, task: &TaskRecord) -> Result<()> {\n        let path = self.tasks_dir.join(format!(\"{}.json\", task.id));\n        write_json_atomic(&path, task)\n    }\n}\n\nfn normalize_hunt_verdict(raw: &str) -> Result<&'static str> {\n    match raw.trim() {\n        \"hunting\" => Ok(\"hunting\"),\n        \"hunted\" => Ok(\"hunted\"),\n        \"wounded\" => Ok(\"wounded\"),\n        \"escaped\" => Ok(\"escaped\"),\n        other => bail!(\n            \"unsupported hunt_verdict task update '{other}'. Expected one of: hunting, hunted, wounded, escaped\"\n        ),\n    }\n}\n\n/// Outcome of loading the persisted task store at boot: the reconciled task\n/// map + queue, plus the ids whose status was flipped running->failed by\n/// crash recovery (the only records boot needs to re-persist).\nstruct LoadedTaskState {\n    tasks: HashMap<String, TaskRecord>,\n    queue: VecDeque<String>,\n    recovered: Vec<String>,\n}\n\nfn load_state(tasks_dir: &Path, queue_path: &Path) -> Result<LoadedTaskState> {\n    let mut tasks = HashMap::new();\n    let mut recovered = Vec::new();\n    if tasks_dir.exists() {","sourceCodeStart":2212,"sourceCodeEnd":2248,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/task_manager.rs#L2212-L2248","documentation":"normalize_hunt_verdict accepts exactly four lowercase verdict strings for hunt-style task updates: hunting, hunted, wounded, escaped. The input is trimmed before matching, but any other value (typos, uppercase forms like 'Hunted', or future verdicts) is rejected with this bail before any task mutation is applied.","triggerScenarios":"Sending a task update with hunt_verdict set to a value outside the four-element set, e.g. 'hunts', 'HUNTED', 'in-progress', or 'killed'; forwarding verdicts from an external tool whose vocabulary differs.","commonSituations":"Integrating a custom status enum that maps 1:1 except for one or two names; schema drift after a rename; hand-crafted JSON payloads in scripts or tests using informal statuses.","solutions":["Map your statuses to the literal set: hunting, hunted, wounded, escaped (lowercase, surrounding whitespace is tolerated).","Normalize input to trim + lowercase before validation so 'Hunted ' passes.","If you believe a new verdict is genuinely needed, add it to normalize_hunt_verdict in the product code and its tests rather than string-matching client-side."],"exampleFix":"// before\nupdate_task(id, json!({\"hunt_verdict\": verdict.as_str()})).await?; // 'HUNTED' fails\n\n// after\nlet verdict = verdict.trim().to_ascii_lowercase();\nif !matches!(verdict.as_str(), \"hunting\" | \"hunted\" | \"wounded\" | \"escaped\") {\n    return Err(anyhow!(\"unknown hunt verdict: {verdict}\"));\n}\nupdate_task(id, json!({\"hunt_verdict\": verdict})).await?;","handlingStrategy":"validation","validationCode":"fn normalize_verdict_or_err(raw: &str) -> Result<&'static str> {\n    match raw.trim() {\n        \"hunting\" | \"hunted\" | \"wounded\" | \"escaped\" => Ok(raw.trim()),\n        other => Err(anyhow!(\"unknown hunt verdict: {other}\")),\n    }\n}","typeGuard":"fn is_hunt_verdict(s: &str) -> bool {\n    matches!(s.trim(), \"hunting\" | \"hunted\" | \"wounded\" | \"escaped\")\n}","tryCatchPattern":null,"preventionTips":["Lowercase and trim verdicts from external systems before sending task updates.","Keep a single constant list of verdicts shared by producer and consumer.","Add new verdicts to normalize_hunt_verdict and its tests together; do not special-case client-side."],"tags":["task","validation","enum","rust"],"backgroundTag":"invalid-enum-value","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}