calesthio/OpenMontage · error · ComfyUIError

Node errors: {json.dumps(data['node_errors'])}

Error message

Node errors: {json.dumps(data['node_errors'])}

What it means

ComfyUIError raised when the ComfyUI /prompt submit endpoint responds with a non-empty node_errors object. ComfyUI validates every node's inputs server-side before queueing; node_errors maps node IDs to validation failures (missing required input, unknown widget value, bad type). The JSON is embedded verbatim so each offending node is identifiable. This happens before any execution, so no GPU time is wasted.

Source

Thrown at tools/_comfyui/client.py:190

            return False

    # ------------------------------------------------------------------
    # Core cycle
    # ------------------------------------------------------------------

    def submit(self, workflow: dict) -> str:
        """Queue a workflow for execution.  Returns the ``prompt_id``."""
        resp = requests.post(
            f"{self.server_url}/prompt",
            json={"prompt": workflow, "client_id": self.client_id},
            timeout=30,
        )
        try:
            data = resp.json()
        except ValueError:
            data = {}
        if data.get("node_errors"):
            raise ComfyUIError(f"Node errors: {json.dumps(data['node_errors'])}")
        if data.get("error"):
            raise ComfyUIError(f"Prompt error: {json.dumps(data['error'])}")
        resp.raise_for_status()
        prompt_id = data.get("prompt_id")
        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:

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Parse the embedded node_errors JSON — each key is the node id and the value names the failing input; fix the workflow at those nodes
  2. Verify every custom node in the workflow is installed on the server (ComfyUI Manager) — missing nodes are a top cause
  3. Re-export the workflow from the same ComfyUI instance you submit to (API format), then re-apply patches with patch_workflow
  4. If a required input is optional server-side, connect it explicitly instead of leaving it absent

Example fix

# before
patches = {"6": {"ckpt_name": "sd_xl_base.safetensors"}}  # model not present

# after
# check available checkpoints first: GET /object_info/CheckpointLoaderSimple
patches = {"6": {"ckpt_name": "sd_xl_turbo_1.0_fp16.safetensors"}}
Defensive patterns

Strategy: validation

Validate before calling

import requests
info = requests.get(f"{server_url}/object_info", timeout=10).json()
# verify every node's class_type exists and required inputs are wired
for nid, node in workflow.items():
    spec = info.get(node["class_type"])
    if spec is None:
        raise SystemExit(f"node {nid}: unknown type {node['class_type']!r} (custom node missing?)")
    required = spec["input"]["required"]
    missing = [k for k in required if k not in node["inputs"] and k not in spec["input"].get("optional", {})]
    if missing:
        raise SystemExit(f"node {nid}: missing required inputs {missing}")

Type guard

def workflow_node_ids_are_valid(workflow: dict, object_info: dict) -> bool:
    return all(n["class_type"] in object_info for n in workflow.values())

Try / catch

try:
    prompt_id = client.submit(workflow)
except ComfyUIError as e:
    if "Node errors" in str(e):
        # parse embedded JSON: {node_id: {errors...}}
        raise SystemExit(f"fix workflow nodes: {e}")
    raise

Prevention

When it happens

Trigger: POSTing a workflow via submit() where at least one node misses a required input, references an unlinked mandatory slot, uses a value the node no longer accepts, or the workflow JSON was exported from a different ComfyUI version with changed node schemas.

Common situations: Custom workflow_json/workflow_path input with hand-edited node ids; missing custom nodes on the server (validation of those nodes fails); ComfyUI upgraded and a node's input contract changed; LoraLoader pointing at a nonexistent lora name; wrong image format field types.

Related errors


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