Comfy-Org/ComfyUI · error · ValueError
job id must be a UUID in canonical lowercase hyphenated form
Error message
job id must be a UUID in canonical lowercase hyphenated form
What it means
Raised by the job-id validator in comfy_execution/jobs.py when the id is a string but not a canonical lowercase-hyphenated UUID. The check is str(uuid.UUID(value)) == value, which rejects uppercase hex, braced forms ({...}), urn:uuid: prefixes, unhyphenated 32-char hex, and any garbage that uuid.UUID would parse-and-normalize differently. Canonical form is enforced because ids are matched verbatim in history, websocket, and /interrupt lookups.
Source
Thrown at comfy_execution/jobs.py:49
ALL = [PENDING, IN_PROGRESS, COMPLETED, FAILED, CANCELLED]
def validate_job_id(value) -> str:
"""Validate a client-supplied job (prompt) id.
Job ids must be UUIDs in the canonical lowercase hyphenated form. The id
is stored and compared verbatim everywhere downstream — history keys,
websocket events, and /interrupt matching — so accepting another spelling
would silently rewrite the client's id and then miss every exact-match
lookup. Rejecting loudly beats that.
Returns the id unchanged. Raises ValueError when the value is not a
string in canonical UUID form.
"""
if not isinstance(value, str):
raise ValueError(f"job id must be a string, got {type(value).__name__}")
if str(uuid.UUID(value)) != value:
raise ValueError("job id must be a UUID in canonical lowercase hyphenated form")
return value
# Media types that can be previewed in the frontend
PREVIEWABLE_MEDIA_TYPES = frozenset({'images', 'video', 'audio', '3d', 'text'})
# 3D file extensions for preview fallback (no dedicated media_type exists)
THREE_D_EXTENSIONS = frozenset({'.obj', '.fbx', '.gltf', '.glb', '.usdz'})
# Text file extensions for preview fallback (the formats SaveText can produce)
TEXT_EXTENSIONS = frozenset({'.txt', '.md', '.json'})
def has_3d_extension(filename: str) -> bool:
lower = filename.lower()
return any(lower.endswith(ext) for ext in THREE_D_EXTENSIONS)
View on GitHub (pinned to 1c6d8d45b3)
Solutions
- Generate ids as str(uuid.uuid4()) — already canonical lowercase hyphenated.
- Normalize existing ids client-side: str(uuid.UUID(raw)) before sending (only works if raw is parseable).
- Replace slug-style ids ('job-42') with per-request UUIDs and keep your own slug->uuid mapping.
- If upgrading a custom client across ComfyUI versions, audit every place a prompt id is produced or echoed.
Example fix
# before prompt_id = uuid.uuid4().hex # '0c9a...' no hyphens -> ValueError prompt_id = str(uuid.uuid4()).upper() # uppercase -> ValueError # after prompt_id = str(uuid.uuid4()) # '0c9a586b-...' canonical form passes
Defensive patterns
Strategy: validation
Validate before calling
import uuid
def canonical_job_id(raw: str) -> str:
return str(uuid.UUID(raw)) # raises if unparseable; output is canonical
prompt_id = canonical_job_id(prompt_id) # safe to send Type guard
def is_canonical_uuid(v) -> bool:
if not isinstance(v, str): return False
try: return str(uuid.UUID(v)) == v
except ValueError: return False Prevention
- Generate ids with str(uuid.uuid4()) — already canonical.
- Never use .hex, .upper(), braces, or urn: prefixes.
- Normalize arbitrary UUID spellings with str(uuid.UUID(raw)) before sending.
When it happens
Trigger: Posting /prompt with prompt_id='ABCDEF...' (uppercase), 'urn:uuid:...', '{...}', a 32-char hex without hyphens, or a random slug like 'my-job-1'. str(uuid.UUID(v)) normalizes all of these, so the equality check fails and the ValueError fires. Note uuid.UUID also raises its own ValueError on totally unparseable input, which surfaces with a different message.
Common situations: Clients using uuid.uuid4().hex (no hyphens) or str(uuid.uuid4()).upper(); ids copied from .NET or enterprise systems in braced/urn form; slugs from job queues reused as prompt ids; older ComfyUI versions that accepted arbitrary strings, breaking custom clients after the strictness change.
Related errors
- job id must be a string, got {type(value).__name__}
- username not provided
- moodboard_id must be a UUID (received {mb_id!r}); copy it fr
- SeedVR2TemporalChunk: temporal_overlap must be >= 0; got {te
- SeedVR2TemporalChunk: frames_per_chunk must be a 4n+1 pixel-
AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14).
Data as JSON: /api/errors/52dcab67b87fa25f.
Report an issue: GitHub.