calesthio/OpenMontage · warning · ComfyUIError

Prompt {prompt_id} did not complete within {timeout}s (webso

Error message

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.

What it means

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.

Source

Thrown at tools/_comfyui/client.py:328

                if data.get("prompt_id") not in (None, prompt_id):
                    continue  # another job sharing this connection
                msg_type = message.get("type")
                if msg_type == "progress":
                    if on_progress:
                        on_progress(data)
                elif msg_type == "execution_error":
                    raise ComfyUIError(f"Execution error: {data}", prompt_id=prompt_id)
                elif msg_type == "executing" and data.get("node") is None:
                    finished = True
                    break
        finally:
            conn.close()

        if not finished:
            entry = self._history_entry_if_reachable(prompt_id)
            if entry is not None:
                return entry
            raise ComfyUIError(
                f"Prompt {prompt_id} did not complete within {timeout}s "
                f"(websocket wait). The job was not cancelled — resume with "
                f"resume_prompt_id={prompt_id!r} and a longer timeout.",
                prompt_id=prompt_id,
            )

        entry = self._history_entry(prompt_id)
        if entry is None:
            raise ComfyUIError(
                f"No history entry for {prompt_id} after completion",
                prompt_id=prompt_id,
            )
        return entry

    def _wait(
        self,
        prompt_id: str,
        *,

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Resume with the embedded resume_prompt_id and a longer timeout — do not resubmit a fresh job
  2. If behind a proxy, raise its websocket read/idle timeout or connect directly to ComfyUI's port
  3. Check GET /history/{prompt_id} once manually to see whether the job already completed
  4. Increase timeout up front for known-heavy workflows

Example fix

# before
entry = client.wait_ws(prompt_id, timeout=600)

# after
entry = client.wait_ws(prompt_id, timeout=3600)
# or resume later: client.generate(..., resume_prompt_id=prompt_id, timeout=3600)
Defensive patterns

Strategy: retry

Validate before calling

import requests
def history_ready(server_url: str, prompt_id: str) -> bool:
    try:
        return prompt_id in requests.get(f"{server_url}/history/{prompt_id}", timeout=5).json()
    except requests.RequestException:
        return False

Try / catch

try:
    entry = client.wait_ws(prompt_id, timeout=600)
except ComfyUIError as e:
    if "(websocket wait)" in str(e):
        pid = getattr(e, "prompt_id", None)
        # job not cancelled — resume instead of resubmitting
        entry = client.poll(pid, timeout=3600) if pid else None
        if entry is None:
            raise
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15). Data as JSON: /api/errors/2158b758e86a8a64. Report an issue: GitHub.