windmill-labs/windmill · warning · TimeoutError
reached timeout
Error message
reached timeout
What it means
wait_job accepts a `timeout` in seconds; if the job has not completed before the deadline, the client cancels the job via the queue cancel endpoint and raises TimeoutError('reached timeout'). This is a deliberate TimeoutError, not a generic Exception.
Source
Thrown at python-client/wmill/wmill/client.py:443
if completed:
result = result_res["result"]
if success:
if result is None and assert_result_is_not_none:
raise Exception("Result was none")
return result
else:
error = result["error"]
raise Exception(f"Job {job_id} was not successful: {str(error)}")
if timeout and ((time.time() - start_time) > timeout):
msg = "reached timeout"
logger.warning(msg)
self.post(
f"/w/{self.workspace}/jobs_u/queue/cancel/{job_id}",
json={"reason": msg},
)
raise TimeoutError(msg)
if verbose:
logger.info(f"sleeping 0.5 seconds for {job_id = }")
time.sleep(0.5)
def cancel_job(self, job_id: str, reason: str = None) -> str:
"""Cancel a specific job by ID.
Args:
job_id: UUID of the job to cancel
reason: Optional reason for cancellation
Returns:
Response message from the cancel endpoint
"""
logger.info(f"cancelling job: {job_id}")
payload = {"reason": reason or "cancelled via cancel_job method"}View on GitHub (pinned to e474e8803c)
Solutions
- Increase the `timeout` parameter to exceed the expected job duration.
- Check worker availability/queue in the Windmill UI if the job never started (queued indefinitely).
- Make the script faster or split it into smaller flows.
- Catch TimeoutError specifically if timeout is an expected outcome.
- Pass timeout=None (or omit) to wait indefinitely, if acceptable.
Example fix
// before result = client.wait_job(job_id, timeout=60) // after result = client.wait_job(job_id, timeout=3600) # long-running ETL
Defensive patterns
Strategy: try-catch
Try / catch
try:
result = client.wait_job(job_id, timeout=expected_max_seconds)
except TimeoutError:
logger.warning('job %s exceeded timeout; was canceled', job_id)
result = None Prevention
- Set timeout generously above the script's worst-case duration.
- Check worker availability if jobs time out while still queued.
- Catch TimeoutError specifically (it is not a plain Exception subclass chain you'd catch generically without including it).
- Monitor job duration in the UI and right-size the timeout.
When it happens
Trigger: wait_job(job_id, timeout=N) where the script/flow runs longer than N seconds; hung job stuck in queue (workers down) or a long-running flow polled with a too-short timeout.
Common situations: Long data-processing script exceeding an arbitrarily chosen timeout; no workers online so the job never starts; polling with default/short timeout after switching to a slower script.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timed out after ${Math.round(CASCADE_JOB_TIMEOUT_MS / 60000)
- Timed out waiting for job ${jobId}
- ${timeoutMessage}
- Job ${jobId} was not successful: ${JSON.stringify(error)}
- Timed out waiting for flow ${id} to complete
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/a01f15edfc8e6f0d.
Report an issue: GitHub.