calesthio/OpenMontage · error · ComfyUIError

No output artifacts on node {output_node}. Available nodes:

Error message

No output artifacts on node {output_node}. Available nodes: {list(outputs.keys())}

What it means

ComfyUIError raised during artifact download when the history entry's outputs contain no items for the requested output_node under any of the artifact keys ComfyUI uses ('images', 'gifs', 'audio', 'video'). The message lists the node ids that DO have outputs, which is the key diagnostic: usually the caller asked for a preview/output node id different from the node that actually saved files.

Source

Thrown at tools/_comfyui/client.py:456

            entry = self.poll(prompt_id, timeout=timeout, interval=interval)
        else:
            entry = self._wait(
                prompt_id, timeout=timeout, interval=interval, on_progress=on_progress
            )

        outputs = entry.get("outputs", {})
        node_output = outputs.get(output_node, {})

        # ComfyUI stores images/video frames under "images", legacy GIFs
        # under "gifs", and the native SaveAudio node's output under "audio".
        items = (
            node_output.get("images", [])
            or node_output.get("gifs", [])
            or node_output.get("audio", [])
            or node_output.get("video", [])
        )
        if not items:
            raise ComfyUIError(
                f"No output artifacts on node {output_node}. "
                f"Available nodes: {list(outputs.keys())}"
            )

        paths: list[Path] = []
        for i, item in enumerate(items):
            suffix = Path(item["filename"]).suffix
            if len(items) == 1:
                target = dest
            else:
                target = dest.with_stem(f"{dest.stem}_{i:03d}").with_suffix(suffix)
            self.download(
                item["filename"],
                item.get("subfolder", ""),
                target,
                item.get("type", "output"),
            )
            paths.append(target)

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Read the 'Available nodes' list in the message and retry with the id that actually holds outputs (the Save* node)
  2. Open the workflow JSON and confirm the save node's id; pass it as output_node (or via the tool's output_node parameter)
  3. If using community nodes whose output key differs (e.g. VHS_VideoCombine), pass the node id of a standard-output node or extend the key list
  4. Ensure the save node is not muted/bypassed (mode 2/4 in UI exports)

Example fix

# before
client.download_output(entry, output_node="3", dest=...)  # KSampler id

# after
client.download_output(entry, output_node="9", dest=...)  # SaveImage id from message's Available nodes
Defensive patterns

Strategy: validation

Validate before calling

# derive a save-node id from the workflow instead of guessing
def find_save_node(workflow: dict) -> str | None:
    for nid, node in workflow.items():
        if node.get("class_type", "").startswith(("Save", "VHS_")):
            return nid
    return None

output_node = output_node or find_save_node(workflow)
if output_node is None:
    raise SystemExit("workflow has no save node; cannot collect artifacts")

Type guard

def node_has_outputs(entry: dict, node_id: str) -> bool:
    out = entry.get("outputs", {}).get(node_id, {})
    return bool(out.get("images") or out.get("gifs") or out.get("audio") or out.get("video"))

Try / catch

try:
    client.download_output(entry, output_node, dest)
except ComfyUIError as e:
    if "No output artifacts" in str(e):
        # message lists Available nodes — pick the Save* id and retry
        available = list(entry.get("outputs", {}).keys())
        retry_node = next((n for n in available if "save" in str(entry['outputs'][n]).lower()), available[0])
        client.download_output(entry, retry_node, dest)
    else:
        raise

Prevention

When it happens

Trigger: Calling the download/collect method with an output_node id that produced no artifacts (e.g. a KSampler node instead of the SaveImage node), or pointing at a PreviewImage whose outputs were consumed; also when the real save node wrote under an unexpected key.

Common situations: Custom workflows with multiple save nodes where the caller guessed the wrong id; workflow re-exported and node ids renumbered; SaveAnimatedWEBP/VHS nodes storing outputs under keys not in the checked list; execution saved zero files because a bypassed node was used.

Related errors


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