{"record":{"id":"972fc1c269cfdc59","repo":"cube-js/cube","slug":"timed-out-after-s-waiting-for-what-last-seen","errorCode":null,"errorMessage":"timed out after {}s waiting for {what} (last seen: {label}). {on_timeout}. Last error: {err}","messagePattern":"timed out after (.+?)s waiting for (.+?) \\(last seen: (.+?)\\)\\. (.+?)\\. Last error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust/cube-cli/src/wait.rs","lineNumber":110,"sourceCode":"    let Wait {\n        what,\n        timeout,\n        interval,\n        on_timeout,\n    } = wait;\n    let started = Instant::now();\n    let mut last_label: Option<String> = None;\n    // The CURRENT failure streak: how many consecutive transient failures, and the\n    // most recent one's message. One variable rather than two, because the count and\n    // the message are only ever meaningful together — and keeping a message past the\n    // streak that produced it is how a blip recovered from at minute 1 ends up blamed\n    // for a timeout at minute 30. `None` between streaks says exactly that.\n    let mut streak: Option<(u32, String)> = None;\n\n    // Same message whether the deadline lands between attempts or inside one.\n    let timed_out =\n        |elapsed: Duration, last_label: &Option<String>, streak: &Option<(u32, String)>| {\n            anyhow::anyhow!(\n                \"timed out after {}s waiting for {what}{}{}{}\",\n                elapsed.as_secs(),\n                match last_label {\n                    Some(label) => format!(\" (last seen: {label})\"),\n                    None => String::new(),\n                },\n                if on_timeout.is_empty() {\n                    String::new()\n                } else {\n                    format!(\". {on_timeout}\")\n                },\n                match streak {\n                    Some((_, err)) => format!(\". Last error: {err}\"),\n                    None => String::new(),\n                }\n            )\n        };\n","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/rust/cube-cli/src/wait.rs#L92-L128","documentation":"`poll` waits for an asynchronous condition (e.g. deployment readiness) by repeatedly running `attempt()` until a terminal value or the deadline. When the deadline passes without a terminal value, it raises this timeout error. The message includes elapsed seconds, what was waited for, the last observed state label, streak info about recurring transient failures, an on-timeout hint, and the last error seen.","triggerScenarios":"Any `poll` call where `attempt()` never returns a terminal value before the computed deadline — e.g. a service never becomes healthy, or attempts keep erroring until `tokio::time::timeout_at(deadline, ...)` expires. Raised in tests `a_never_answering_attempt_still_times_out`, `an_answer_after_the_deadline_is_not_accepted`, and others.","commonSituations":"Waiting for a deployment/pod that is crash-looping, a service that starts slower than the configured timeout, or a perpetually failing check (bad endpoint) whose transient errors keep repeating (streak noted in message).","solutions":["Read the message: `last seen` and `Last error` identify what the wait was actually observing.","Increase the timeout if the target is known to be slow (deadline may land inside an attempt; late answers are rejected).","Fix the underlying condition the last error points at (e.g. crash-looping container, wrong health endpoint).","Check network/firewall if attempts error transiently forever (the streak counter flags recurring failures)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match poll(what, attempt, timeout).await {\n    Err(e) if e.to_string().starts_with(\"timed out after\") => {\n        // parse \"last seen\"/\"Last error\" from the message, decide to retry with longer timeout\n    }\n    other => other?,\n}","preventionTips":["Set timeouts with headroom for slow starts","Monitor the target condition independently so timeout doesn't mask the real failure","Use the streak/last-error info in the message to fix root causes instead of blindly retrying"],"tags":["timeout","async","tokio","polling"],"backgroundTag":"operation-timed-out","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}