windmill-labs/windmill · error
Timed out waiting for flow ${id} to complete
Error message
Timed out waiting for flow ${id} to complete What it means
`wmill flow run` polls the queued flow job for completion and gives up after MAX_RETRIES (with 100ms sleeps), throwing this timeout. It means the flow did not reach a terminal state within the polling budget, not necessarily that the flow failed.
Source
Thrown at cli/src/commands/flow/flow.ts:595
if (jobInfo.success === false) {
process.exitCode = 1;
}
if (opts.silent) {
console.log(JSON.stringify(jobInfo.result ?? {}));
} else {
log.info(JSON.stringify(jobInfo.result ?? {}, null, 2));
}
break;
} catch {
retries++;
await new Promise((resolve) => setTimeout(resolve, 100));
}
}
if (retries >= MAX_RETRIES) {
throw new Error(`Timed out waiting for flow ${id} to complete`);
}
}
async function preview(
opts: GlobalOptions & {
data?: string;
silent: boolean;
remote?: boolean;
step?: string;
tag?: string;
} & SyncOptions,
flowPath: string
) {
if (opts.silent) {
log.setSilent(true);
}
const useLocalPathScripts = !opts.remote;
// Captured before the config read, which chdirs to the wmill.yaml root.View on GitHub (pinned to e474e8803c)
Solutions
- Re-run with a longer wait or check the run in the web UI / `wmill flow status` to see if it eventually completed
- Check that workers are running and consuming from the right tag/queue
- Reduce flow runtime or split it; use schedules/webhooks instead of blocking CLI runs
- Check network stability between CLI and the instance
Example fix
// before wmill flow run u/myuser/etl_flow // after wmill flow run u/myuser/etl_flow --async && wmill flow status <jobId>
Defensive patterns
Strategy: try-catch
Validate before calling
// Nothing to check before; instead pick --async for flows that may exceed the poll window if (flowMayRunLong) useAsyncMode = true;
Try / catch
try {
await client.flow.run(flowPath);
} catch (e) {
if (String(e).startsWith('Timed out waiting for flow')) {
// job may still be running: check status instead of re-queuing
const status = await checkFlowRunStatus(jobId);
}
} Prevention
- Use `--async` (or webhook/schedule) for long-running flows
- Confirm workers are online and tagged for the flow's tag
- Monitor queue depth on the instance before batch runs
- Don't assume timeout = failure; check the job in the UI
When it happens
Trigger: `wmill flow run <path>` where the flow runs longer than the retry window, or the poll loop cannot read the job (the catch branch also increments retries on transient API errors).
Common situations: Long-running flows (scheduled loads, heavy scripts); slow workers or no worker picking up the job; transient network/auth hiccups during polling consuming the retry budget.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timed out waiting for job ${id}
- Timed out waiting for job ${id} to complete
- Giving up polling job ${jobId} after ${MAX_CONSECUTIVE_POLL_
- Failed to poll dependencies job ${jobId}: ${e?.message ?? e}
- Failed to poll dependencies job ${jobId}: ${e?.message ?? e}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/b54ae0ad5d394fc4.
Report an issue: GitHub.