{"record":{"id":"fd8716706102cc48","repo":"calesthio/OpenMontage","slug":"no-output-artifacts-on-node-output-node-availab","errorCode":null,"errorMessage":"No output artifacts on node {output_node}. Available nodes: {list(outputs.keys())}","messagePattern":"No output artifacts on node (.+?)\\. Available nodes: (.+?)","errorType":"exception","errorClass":"ComfyUIError","httpStatus":null,"severity":"error","filePath":"tools/_comfyui/client.py","lineNumber":456,"sourceCode":"            entry = self.poll(prompt_id, timeout=timeout, interval=interval)\n        else:\n            entry = self._wait(\n                prompt_id, timeout=timeout, interval=interval, on_progress=on_progress\n            )\n\n        outputs = entry.get(\"outputs\", {})\n        node_output = outputs.get(output_node, {})\n\n        # ComfyUI stores images/video frames under \"images\", legacy GIFs\n        # under \"gifs\", and the native SaveAudio node's output under \"audio\".\n        items = (\n            node_output.get(\"images\", [])\n            or node_output.get(\"gifs\", [])\n            or node_output.get(\"audio\", [])\n            or node_output.get(\"video\", [])\n        )\n        if not items:\n            raise ComfyUIError(\n                f\"No output artifacts on node {output_node}. \"\n                f\"Available nodes: {list(outputs.keys())}\"\n            )\n\n        paths: list[Path] = []\n        for i, item in enumerate(items):\n            suffix = Path(item[\"filename\"]).suffix\n            if len(items) == 1:\n                target = dest\n            else:\n                target = dest.with_stem(f\"{dest.stem}_{i:03d}\").with_suffix(suffix)\n            self.download(\n                item[\"filename\"],\n                item.get(\"subfolder\", \"\"),\n                target,\n                item.get(\"type\", \"output\"),\n            )\n            paths.append(target)","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/_comfyui/client.py#L438-L474","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the 'Available nodes' list in the message and retry with the id that actually holds outputs (the Save* node)","Open the workflow JSON and confirm the save node's id; pass it as output_node (or via the tool's output_node parameter)","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","Ensure the save node is not muted/bypassed (mode 2/4 in UI exports)"],"exampleFix":"# before\nclient.download_output(entry, output_node=\"3\", dest=...)  # KSampler id\n\n# after\nclient.download_output(entry, output_node=\"9\", dest=...)  # SaveImage id from message's Available nodes","handlingStrategy":"validation","validationCode":"# derive a save-node id from the workflow instead of guessing\ndef find_save_node(workflow: dict) -> str | None:\n    for nid, node in workflow.items():\n        if node.get(\"class_type\", \"\").startswith((\"Save\", \"VHS_\")):\n            return nid\n    return None\n\noutput_node = output_node or find_save_node(workflow)\nif output_node is None:\n    raise SystemExit(\"workflow has no save node; cannot collect artifacts\")","typeGuard":"def node_has_outputs(entry: dict, node_id: str) -> bool:\n    out = entry.get(\"outputs\", {}).get(node_id, {})\n    return bool(out.get(\"images\") or out.get(\"gifs\") or out.get(\"audio\") or out.get(\"video\"))","tryCatchPattern":"try:\n    client.download_output(entry, output_node, dest)\nexcept ComfyUIError as e:\n    if \"No output artifacts\" in str(e):\n        # message lists Available nodes — pick the Save* id and retry\n        available = list(entry.get(\"outputs\", {}).keys())\n        retry_node = next((n for n in available if \"save\" in str(entry['outputs'][n]).lower()), available[0])\n        client.download_output(entry, retry_node, dest)\n    else:\n        raise","preventionTips":["Always pass the Save* node id, not a sampler/preview id","Recompute node ids from the workflow JSON rather than hardcoding","Unmute/unbypass save nodes before exporting the workflow"],"tags":["comfyui","artifacts","node-id","workflow"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}