{"record":{"id":"a01f15edfc8e6f0d","repo":"windmill-labs/windmill","slug":"reached-timeout","errorCode":null,"errorMessage":"reached timeout","messagePattern":"reached timeout","errorType":"exception","errorClass":"TimeoutError","httpStatus":null,"severity":"warning","filePath":"python-client/wmill/wmill/client.py","lineNumber":443,"sourceCode":"\n            if completed:\n                result = result_res[\"result\"]\n                if success:\n                    if result is None and assert_result_is_not_none:\n                        raise Exception(\"Result was none\")\n                    return result\n                else:\n                    error = result[\"error\"]\n                    raise Exception(f\"Job {job_id} was not successful: {str(error)}\")\n\n            if timeout and ((time.time() - start_time) > timeout):\n                msg = \"reached timeout\"\n                logger.warning(msg)\n                self.post(\n                    f\"/w/{self.workspace}/jobs_u/queue/cancel/{job_id}\",\n                    json={\"reason\": msg},\n                )\n                raise TimeoutError(msg)\n            if verbose:\n                logger.info(f\"sleeping 0.5 seconds for {job_id = }\")\n\n            time.sleep(0.5)\n\n    def cancel_job(self, job_id: str, reason: str = None) -> str:\n        \"\"\"Cancel a specific job by ID.\n\n        Args:\n            job_id: UUID of the job to cancel\n            reason: Optional reason for cancellation\n\n        Returns:\n            Response message from the cancel endpoint\n        \"\"\"\n        logger.info(f\"cancelling job: {job_id}\")\n\n        payload = {\"reason\": reason or \"cancelled via cancel_job method\"}","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/python-client/wmill/wmill/client.py#L425-L461","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nresult = client.wait_job(job_id, timeout=60)\n// after\nresult = client.wait_job(job_id, timeout=3600)  # long-running ETL","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = client.wait_job(job_id, timeout=expected_max_seconds)\nexcept TimeoutError:\n    logger.warning('job %s exceeded timeout; was canceled', job_id)\n    result = None","preventionTips":["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."],"tags":["timeout","jobs","polling","python"],"backgroundTag":"operation-timed-out","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}