{"record":{"id":"4e5633a0ec5999d5","repo":"Hmbown/CodeWhale","slug":"timed-out-waiting-for-task-task-id","errorCode":null,"errorMessage":"Timed out waiting for task {task_id}","messagePattern":"Timed out waiting for task (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/task_manager.rs","lineNumber":3480,"sourceCode":"    }\n    primary\n}\n\n/// Wait for a task to reach a terminal status (tests and API helpers).\n#[cfg(test)]\npub async fn wait_for_terminal_state(\n    manager: &TaskManager,\n    task_id: &str,\n    timeout: StdDuration,\n) -> Result<TaskRecord> {\n    let deadline = std::time::Instant::now() + timeout;\n    loop {\n        let task = manager.get_task(task_id).await?;\n        if task.status.is_terminal() {\n            return Ok(task);\n        }\n        if std::time::Instant::now() >= deadline {\n            bail!(\"Timed out waiting for task {task_id}\");\n        }\n        sleep(StdDuration::from_millis(50)).await;\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::test_support::{EnvVarGuard, lock_test_env};\n    use std::fs;\n    use std::sync::atomic::{AtomicUsize, Ordering};\n    use tokio::time::Duration;\n\n    struct MockExecutor;\n\n    fn provider_default_model_cases() -> Vec<(&'static str, Config, &'static str)> {\n        let deepseek = Config {\n            provider: Some(\"deepseek\".to_string()),","sourceCodeStart":3462,"sourceCodeEnd":3498,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/task_manager.rs#L3462-L3498","documentation":"A wait helper polls the task every 50 ms via get_task until its status is terminal; if the deadline passes first it throws 'Timed out waiting for task {task_id}'. It signals that the task did not reach a terminal state within the allowed timeout, not that the task failed itself.","triggerScenarios":"Awaiting task completion with a timeout that expires while the task is still running or stuck in a non-terminal status (queued/running).","commonSituations":"Long-running subagent work exceeding the default wait budget; a hung task (deadlocked tool, stalled network call); system under heavy load slowing the task loop.","solutions":["Check the task's current status with get_task/list — it may still be running; re-wait with a longer deadline if progress is being made.","Cancel or reap the stuck task if it is genuinely hung, then retry the work.","Investigate the task's own logs for a deadlock or blocking call that prevents reaching a terminal state."],"exampleFix":"// before\nlet task = manager.wait_for_task(id, Duration::from_secs(30)).await?;\n// after\nlet task = match manager.wait_for_task(id, Duration::from_secs(30)).await {\n    Ok(t) => t,\n    Err(_) => { manager.cancel_task(id).await?; manager.wait_for_task(id, Duration::from_secs(30)).await? }\n};","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"let task = match manager.wait_for_task(id, timeout).await {\n    Ok(t) => t,\n    Err(e) if e.to_string().contains(\"Timed out waiting\") => {\n        // inspect status, extend deadline or cancel\n        manager.cancel_task(id).await?;\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n};","preventionTips":["Size the timeout to the task's expected worst-case duration.","Poll status and log progress so hangs are distinguishable from slow work.","Always have a cancel/reap path for tasks that miss their deadline."],"tags":["timeout","async","task-management"],"backgroundTag":"request-timeout","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}