windmill-labs/windmill · error

Timed out waiting for job ${jobId}

Error message

Timed out waiting for job ${jobId}

What it means

When waiting for a cascade job (pipeline recording processing), the session polls the job status every CASCADE_POLL_INTERVAL_MS, tolerating transient errors, until it completes. If the job is still not completed when the polling budget is exhausted, it gives up with 'Timed out waiting for job <id>'.

Source

Thrown at frontend/src/lib/components/workspaceSettings/deployToHubSession.svelte.ts:1826

	// timeout (DuckLake/DuckDB steps routinely exceed a few minutes). Adds the
	// `#pipelineRunTok` cancellation the shared `makeWaitJobTerminal` lacks.
	async #waitJobTerminal(jobId: string, tok: number): Promise<'success' | 'failure'> {
		const deadline = Date.now() + CASCADE_JOB_TIMEOUT_MS
		while (Date.now() < deadline) {
			if (tok !== this.#pipelineRunTok) throw new Error('cancelled')
			try {
				const r = await JobService.getCompletedJobResultMaybe({
					workspace: this.workspace,
					id: jobId,
					getStarted: false
				})
				if (r.completed) return r.success ? 'success' : 'failure'
			} catch {
				// transient — retry on the next tick
			}
			await sleep(CASCADE_POLL_INTERVAL_MS)
		}
		throw new Error(`Timed out waiting for job ${jobId}`)
	}

	/** Save the captured pipeline recording to the Hub, scoped to the project
	 * (a pipeline is the whole folder, not a single Hub item). Returns true on
	 * success. */
	async savePipelineRecording(): Promise<boolean> {
		const recording = this.pipelineRecordingResult
		if (!recording || this.pipelineRunState !== 'success') return false
		if (this.phase === 'predeploy') {
			sendUserToast(`Push the project to the Hub first before saving its pipeline recording`, true)
			return false
		}
		try {
			await this.#postHub(`/hub/projects/${this.hubSlug}/pipeline_recording`, { recording })
			this.pipelineRecorded = true
			sendUserToast(`Pipeline recording saved`)
			return true
		} catch (e: any) {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Check the job's final state by id on the Hub — it may have completed after the client gave up
  2. Retry the operation (re-save the recording) if the job failed or is stuck
  3. Increase CASCADE_POLL_INTERVAL_MS budget/timeout if large recordings legitimately take longer
  4. Inspect Hub worker logs for the job id to find why it never completed
Defensive patterns

Strategy: retry

Try / catch

try {
  await session.savePipelineRecording()
} catch (e) {
  const m = /Timed out waiting for job (\S+)/.exec(String(e.message))
  if (m) {
    // re-query job status by m[1] — it may have completed after the client timed out
  }
}

Prevention

When it happens

Trigger: A Hub-side job (e.g. processing a saved pipeline recording) runs longer than the allotted polling window, or the polling requests keep failing transiently until the deadline passes.

Common situations: Hub backend busy or processing very large recordings; repeated network errors during polling; job stuck server-side (worker crashed) so it never reaches completed.

Understand the failure class

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/69a3cb8b559f4d0a. Report an issue: GitHub.