{"record":{"id":"7132dea2a388ee96","repo":"calesthio/OpenMontage","slug":"node-node-id-r-not-found-in-workflow-available","errorCode":null,"errorMessage":"Node {node_id!r} not found in workflow. Available: {list(w.keys())}","messagePattern":"Node (.+?) not found in workflow\\. Available: (.+?)","errorType":"exception","errorClass":"ComfyUIError","httpStatus":null,"severity":"error","filePath":"tools/_comfyui/client.py","lineNumber":496,"sourceCode":"    # Workflow helpers\n    # ------------------------------------------------------------------\n\n    @staticmethod\n    def load_workflow(path: Path) -> dict:\n        \"\"\"Load a workflow JSON template from disk.\"\"\"\n        with open(path) as f:\n            return json.load(f)\n\n    @staticmethod\n    def patch_workflow(workflow: dict, patches: dict[str, dict[str, Any]]) -> dict:\n        \"\"\"Deep-copy *workflow* and apply *patches*.\n\n        *patches* maps ``node_id`` → ``{input_name: value, ...}``.\n        \"\"\"\n        w = copy.deepcopy(workflow)\n        for node_id, values in patches.items():\n            if node_id not in w:\n                raise ComfyUIError(\n                    f\"Node {node_id!r} not found in workflow. \"\n                    f\"Available: {list(w.keys())}\"\n                )\n            for key, val in values.items():\n                w[node_id][\"inputs\"][key] = val\n        return w\n\n    @staticmethod\n    def random_seed() -> int:\n        \"\"\"Return a random seed suitable for ComfyUI noise nodes.\"\"\"\n        return random.randint(0, 2**32 - 1)\n","sourceCodeStart":478,"sourceCodeEnd":508,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/_comfyui/client.py#L478-L508","documentation":"ComfyUIError raised by the static patch_workflow helper when a patch references a node_id that is not a key in the workflow dict. patch_workflow deep-copies the graph and writes values into w[node_id]['inputs'][key]; an unknown id means the patch targets nothing. The message lists the workflow's actual node ids so the correct one can be chosen immediately.","triggerScenarios":"Passing patches keyed by node ids from a different export of the workflow (ids renumbered between UI/API format saves), hand-written patch dicts guessing ids, or ids copied from a tutorial workflow that differs from yours.","commonSituations":"Workflow re-exported after edits and node ids shifted ('3' became '10'); using a community workflow where the README's patch examples reference its author's ids; string vs int id confusion (patch keys must match the workflow's id strings exactly).","solutions":["Use the 'Available' list in the message to pick the correct node id and rebuild the patch dict","Inspect the workflow JSON: each top-level key is a node id; find the node whose class_type matches what you want to patch (e.g. KSampler for seed/steps)","Prefer semantic lookup: find the id programmatically by class_type instead of hardcoding","Keep patches next to the exact workflow file they belong to so they never drift"],"exampleFix":"# before\npatches = {\"6\": {\"seed\": 42}}  # id 6 absent\nworkflow = ComfyUIClient.patch_workflow(wf, patches)\n\n# after\nseed_node = next(nid for nid, n in wf.items() if n[\"class_type\"] == \"KSampler\")\nworkflow = ComfyUIClient.patch_workflow(wf, {seed_node: {\"seed\": 42}})","handlingStrategy":"type-guard","validationCode":"def find_nodes_by_class(workflow: dict, class_type: str) -> list[str]:\n    return [nid for nid, n in workflow.items() if n.get(\"class_type\") == class_type]\n\nseed_nodes = find_nodes_by_class(workflow, \"KSampler\")\nif not seed_nodes:\n    raise SystemExit(\"workflow has no KSampler node to patch\")\npatches = {seed_nodes[0]: {\"seed\": 42}}","typeGuard":"def patches_are_valid(workflow: dict, patches: dict) -> bool:\n    return all(nid in workflow for nid in patches)","tryCatchPattern":"try:\n    wf = ComfyUIClient.patch_workflow(workflow, patches)\nexcept ComfyUIError as e:\n    if \"not found in workflow\" in str(e):\n        raise SystemExit(\"patch node id stale — re-derive ids from the current workflow JSON\")\n    raise","preventionTips":["Derive node ids programmatically by class_type; never hardcode ids from other exports","Re-validate patches whenever the workflow file is re-exported","Store patch dicts alongside the exact workflow file they target"],"tags":["comfyui","workflow","patching","node-id"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}