calesthio/OpenMontage · warning · ComfyUIError
Prompt {prompt_id} did not complete within {timeout}s. The j
Error message
Prompt {prompt_id} did not complete within {timeout}s. The job is very likely still running on the ComfyUI server (local/custom workflows on modest GPUs routinely exceed the client wait) — it was not cancelled. Poll GET {{server_url}}/history/{prompt_id} directly, or call generate()/execute() again with a longer timeout and this prompt_id to resume waiting without resubmitting. What it means
ComfyUIError raised by poll() when the prompt has not produced a completed history entry within the client-side timeout (default 600s, 5s interval). Crucially the job is NOT cancelled server-side — ComfyUI keeps executing; the error message carries prompt_id so you can resume waiting via generate()/execute() with the same prompt_id instead of resubmitting (and paying GPU time again). This is a client patience limit, not a server failure.
Source
Thrown at tools/_comfyui/client.py:213
if not prompt_id:
raise ComfyUIError(f"No prompt_id in response: {data}")
return prompt_id
def poll(
self,
prompt_id: str,
*,
timeout: int = 600,
interval: int = 5,
) -> dict:
"""Block until *prompt_id* finishes. Returns the history entry."""
deadline = time.time() + timeout
while time.time() < deadline:
entry = self._history_entry(prompt_id)
if entry is not None:
return entry
time.sleep(interval)
raise ComfyUIError(
f"Prompt {prompt_id} did not complete within {timeout}s. "
f"The job is very likely still running on the ComfyUI server "
f"(local/custom workflows on modest GPUs routinely exceed the "
f"client wait) — it was not cancelled. Poll "
f"GET {{server_url}}/history/{prompt_id} directly, or call "
f"generate()/execute() again with a longer timeout and this "
f"prompt_id to resume waiting without resubmitting.",
prompt_id=prompt_id,
)
def _history_entry(self, prompt_id: str) -> dict | None:
"""Return a completed history entry, or ``None`` while it is absent."""
resp = requests.get(f"{self.server_url}/history/{prompt_id}", timeout=10)
resp.raise_for_status()
entry = resp.json().get(prompt_id)
if entry is None:
return None
status = entry.get("status", {})View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Retry the call with the SAME prompt_id and a longer timeout — the job continues server-side (e.g. timeout=3600)
- Poll GET {server_url}/history/{prompt_id} directly to watch progress without the client
- Pre-warm models (run a tiny job first) and keep queues empty before long generations
- Raise the timeout argument up front for known-heavy workflows instead of relying on the 600s default
Example fix
# before entry = client.poll(prompt_id) # default timeout=600 # after entry = client.poll(prompt_id, timeout=3600, interval=10)
Defensive patterns
Strategy: retry
Validate before calling
import requests
def queue_depth(server_url: str) -> int:
q = requests.get(f"{server_url}/queue", timeout=5).json()
return len(q.get("queue_running", [])) + len(q.get("queue_pending", []))
if queue_depth(server_url) > 2:
print("warning: ComfyUI queue is deep; long waits likely") Try / catch
def poll_with_resume(client, prompt_id, timeouts=(600, 1800, 7200)):
for t in timeouts:
try:
return client.poll(prompt_id, timeout=t)
except ComfyUIError as e:
if "did not complete within" not in str(e):
raise
raise RuntimeError("job never completed; inspect server manually") Prevention
- Pass timeout proportional to expected job cost (video ≫ images)
- Reuse prompt_id on resume — never resubmit a still-running job
- Pre-warm model loads with a tiny job first
- Monitor GET /history/{prompt_id} out-of-band for long runs
When it happens
Trigger: Polling a heavy local workflow (SDXL/high-res video, custom multi-stage graphs) on a modest GPU where 600s isn't enough; queue congestion because other jobs are ahead; long model-load times on first run when weights download or swap from disk.
Common situations: Default 600s timeout used for video-generation workflows that take 20-40 min; ComfyUI on a shared box with a deep queue; cold start downloading a 6GB checkpoint inside the job.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Prompt {prompt_id} did not complete within {timeout}s (webso
- Execution error: {msgs}
- Checkpoint artifacts must be a dictionary
- Backlot server did not become healthy
- Node errors: {json.dumps(data['node_errors'])}
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/1a96c9fe670e7f03.
Report an issue: GitHub.