{"record":{"id":"2158b758e86a8a64","repo":"calesthio/OpenMontage","slug":"prompt-prompt-id-did-not-complete-within-timeou-2158b7","errorCode":null,"errorMessage":"Prompt {prompt_id} did not complete within {timeout}s (websocket wait). The job was not cancelled — resume with resume_prompt_id={prompt_id!r} and a longer timeout.","messagePattern":"Prompt (.+?) did not complete within (.+?)s \\(websocket wait\\)\\. The job was not cancelled — resume with resume_prompt_id=(.+?) and a longer timeout\\.","errorType":"exception","errorClass":"ComfyUIError","httpStatus":null,"severity":"warning","filePath":"tools/_comfyui/client.py","lineNumber":328,"sourceCode":"                if data.get(\"prompt_id\") not in (None, prompt_id):\n                    continue  # another job sharing this connection\n                msg_type = message.get(\"type\")\n                if msg_type == \"progress\":\n                    if on_progress:\n                        on_progress(data)\n                elif msg_type == \"execution_error\":\n                    raise ComfyUIError(f\"Execution error: {data}\", prompt_id=prompt_id)\n                elif msg_type == \"executing\" and data.get(\"node\") is None:\n                    finished = True\n                    break\n        finally:\n            conn.close()\n\n        if not finished:\n            entry = self._history_entry_if_reachable(prompt_id)\n            if entry is not None:\n                return entry\n            raise ComfyUIError(\n                f\"Prompt {prompt_id} did not complete within {timeout}s \"\n                f\"(websocket wait). The job was not cancelled — resume with \"\n                f\"resume_prompt_id={prompt_id!r} and a longer timeout.\",\n                prompt_id=prompt_id,\n            )\n\n        entry = self._history_entry(prompt_id)\n        if entry is None:\n            raise ComfyUIError(\n                f\"No history entry for {prompt_id} after completion\",\n                prompt_id=prompt_id,\n            )\n        return entry\n\n    def _wait(\n        self,\n        prompt_id: str,\n        *,","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/_comfyui/client.py#L310-L346","documentation":"ComfyUIError raised by wait_ws when the websocket wait loop ends without receiving the 'executing node=None' completion frame for this prompt within the timeout. Before raising, it makes a best-effort history probe (_history_entry_if_reachable): if the job actually finished, the entry is returned instead. Only when history is inconclusive does it raise, embedding resume_prompt_id so the caller can continue waiting without resubmitting — the job was not cancelled.","triggerScenarios":"Long jobs exceeding the websocket timeout; the socket dropped/reconnected mid-run (server restart, proxy idle timeout); ComfyUI finished the job but the completion frame was missed and history was momentarily unreachable.","commonSituations":"Nginx/proxy websocket idle timeouts killing the connection during a 30-minute video job; ComfyUI restarted under load; default timeout too small for heavy local workflows; shared server where many jobs compete.","solutions":["Resume with the embedded resume_prompt_id and a longer timeout — do not resubmit a fresh job","If behind a proxy, raise its websocket read/idle timeout or connect directly to ComfyUI's port","Check GET /history/{prompt_id} once manually to see whether the job already completed","Increase timeout up front for known-heavy workflows"],"exampleFix":"# before\nentry = client.wait_ws(prompt_id, timeout=600)\n\n# after\nentry = client.wait_ws(prompt_id, timeout=3600)\n# or resume later: client.generate(..., resume_prompt_id=prompt_id, timeout=3600)","handlingStrategy":"retry","validationCode":"import requests\ndef history_ready(server_url: str, prompt_id: str) -> bool:\n    try:\n        return prompt_id in requests.get(f\"{server_url}/history/{prompt_id}\", timeout=5).json()\n    except requests.RequestException:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    entry = client.wait_ws(prompt_id, timeout=600)\nexcept ComfyUIError as e:\n    if \"(websocket wait)\" in str(e):\n        pid = getattr(e, \"prompt_id\", None)\n        # job not cancelled — resume instead of resubmitting\n        entry = client.poll(pid, timeout=3600) if pid else None\n        if entry is None:\n            raise\n    else:\n        raise","preventionTips":["Raise proxy websocket idle timeouts or bypass the proxy for /ws","Size timeout to worst-case job duration, not average","On timeout, always resume by prompt_id rather than resubmitting"],"tags":["comfyui","websocket","timeout","long-running"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}