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

  1. Increase the `timeout` parameter to exceed the expected job duration.
  2. Check worker availability/queue in the Windmill UI if the job never started (queued indefinitely).
  3. Make the script faster or split it into smaller flows.
  4. Catch TimeoutError specifically if timeout is an expected outcome.
  5. 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

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

Related errors


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