Hmbown/CodeWhale · warning
Timed out waiting for task
Error message
Timed out waiting for task {task_id} What it means
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.
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.
Example fix
// before
let task = manager.wait_for_task(id, Duration::from_secs(30)).await?;
// after
let task = match manager.wait_for_task(id, Duration::from_secs(30)).await {
Ok(t) => t,
Err(_) => { manager.cancel_task(id).await?; manager.wait_for_task(id, Duration::from_secs(30)).await? }
}; Defensive patterns
Strategy: retry
Try / catch
let task = match manager.wait_for_task(id, timeout).await {
Ok(t) => t,
Err(e) if e.to_string().contains("Timed out waiting") => {
// inspect status, extend deadline or cancel
manager.cancel_task(id).await?;
return Err(e);
}
Err(e) => return Err(e),
}; Prevention
- 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.
When it happens
Trigger: Awaiting task completion with a timeout that expires while the task is still running or stuck in a non-terminal status (queued/running).
Common situations: 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.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- LSP semantic request timed out
- Ambiguous task prefix
- background hook supervisor queue is full
- ChatGPT revoke task was lost
- child-local search
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/4e5633a0ec5999d5.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/task_manager.rs:3480
}
primary
}
/// Wait for a task to reach a terminal status (tests and API helpers).
#[cfg(test)]
pub async fn wait_for_terminal_state(
manager: &TaskManager,
task_id: &str,
timeout: StdDuration,
) -> Result<TaskRecord> {
let deadline = std::time::Instant::now() + timeout;
loop {
let task = manager.get_task(task_id).await?;
if task.status.is_terminal() {
return Ok(task);
}
if std::time::Instant::now() >= deadline {
bail!("Timed out waiting for task {task_id}");
}
sleep(StdDuration::from_millis(50)).await;
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_support::{EnvVarGuard, lock_test_env};
use std::fs;
use std::sync::atomic::{AtomicUsize, Ordering};
use tokio::time::Duration;
struct MockExecutor;
fn provider_default_model_cases() -> Vec<(&'static str, Config, &'static str)> {
let deepseek = Config {
provider: Some("deepseek".to_string()),View on GitHub (pinned to 73e0f67d83)