cube-js/cube · error
timed out after {}s waiting for {what} (last seen: {label}).
Error message
timed out after {}s waiting for {what} (last seen: {label}). {on_timeout}. Last error: {err} What it means
`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.
Source
Thrown at rust/cube-cli/src/wait.rs:110
let Wait {
what,
timeout,
interval,
on_timeout,
} = wait;
let started = Instant::now();
let mut last_label: Option<String> = None;
// The CURRENT failure streak: how many consecutive transient failures, and the
// most recent one's message. One variable rather than two, because the count and
// the message are only ever meaningful together — and keeping a message past the
// streak that produced it is how a blip recovered from at minute 1 ends up blamed
// for a timeout at minute 30. `None` between streaks says exactly that.
let mut streak: Option<(u32, String)> = None;
// Same message whether the deadline lands between attempts or inside one.
let timed_out =
|elapsed: Duration, last_label: &Option<String>, streak: &Option<(u32, String)>| {
anyhow::anyhow!(
"timed out after {}s waiting for {what}{}{}{}",
elapsed.as_secs(),
match last_label {
Some(label) => format!(" (last seen: {label})"),
None => String::new(),
},
if on_timeout.is_empty() {
String::new()
} else {
format!(". {on_timeout}")
},
match streak {
Some((_, err)) => format!(". Last error: {err}"),
None => String::new(),
}
)
};
View on GitHub (pinned to 7d981676b3)
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).
Defensive patterns
Strategy: retry
Try / catch
match poll(what, attempt, timeout).await {
Err(e) if e.to_string().starts_with("timed out after") => {
// parse "last seen"/"Last error" from the message, decide to retry with longer timeout
}
other => other?,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- wait timeout is too large
- BigQuery job timeout reached ${this.options.pollTimeout}ms
- DremioQuery job timeout reached ${this.config.pollTimeout}ms
- nothing is building branch {branch} (status {status}{}). If
- Athena job timeout reached ${this.config.pollTimeout}ms
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/972fc1c269cfdc59.
Report an issue: GitHub.