{"record":{"id":"00e1700d0f53b7a8","repo":"Comfy-Org/ComfyUI","slug":"node-node-id-not-found","errorCode":null,"errorMessage":"Node {node_id} not found","messagePattern":"Node (.+?) not found","errorType":"exception","errorClass":"NodeNotFoundError","httpStatus":null,"severity":"error","filePath":"comfy_execution/graph.py","lineNumber":35,"sourceCode":"\nclass NodeNotFoundError(Exception):\n    pass\n\nclass DynamicPrompt:\n    def __init__(self, original_prompt):\n        # The original prompt provided by the user\n        self.original_prompt = original_prompt\n        # Any extra pieces of the graph created during execution\n        self.ephemeral_prompt = {}\n        self.ephemeral_parents = {}\n        self.ephemeral_display = {}\n\n    def get_node(self, node_id):\n        if node_id in self.ephemeral_prompt:\n            return self.ephemeral_prompt[node_id]\n        if node_id in self.original_prompt:\n            return self.original_prompt[node_id]\n        raise NodeNotFoundError(f\"Node {node_id} not found\")\n\n    def has_node(self, node_id):\n        return node_id in self.original_prompt or node_id in self.ephemeral_prompt\n\n    def add_ephemeral_node(self, node_id, node_info, parent_id, display_id):\n        self.ephemeral_prompt[node_id] = node_info\n        self.ephemeral_parents[node_id] = parent_id\n        self.ephemeral_display[node_id] = display_id\n\n    def get_real_node_id(self, node_id):\n        while node_id in self.ephemeral_parents:\n            node_id = self.ephemeral_parents[node_id]\n        return node_id\n\n    def get_parent_node_id(self, node_id):\n        return self.ephemeral_parents.get(node_id, None)\n\n    def get_display_node_id(self, node_id):","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_execution/graph.py#L17-L53","documentation":"Raised as NodeNotFoundError by DynamicPrompt.get_node() in comfy_execution/graph.py when a node id is looked up in neither the ephemeral prompt (nodes created during execution) nor the original user prompt. The dynamic prompt is the execution engine's view of the graph; lookups happen constantly during topo-sort and cache validation, so this indicates the graph state and the request disagree.","triggerScenarios":"Execution machinery references a node id that was never queued: a malformed prompt JSON where an inputs link points at a nonexistent node id, a node deleted from the prompt between queueing and execution, or custom code calling dynprompt.get_node() with a stale id (e.g. from cached validation results).","commonSituations":"Hand-built prompt dicts (API users) with link arrays [\"node_id\", output_index] referencing a typo'd or omitted node; races where the frontend mutates the workflow while the queue processes it; custom nodes manipulating prompt structures; or clients resubmitting a partially-patched prompt from history.","solutions":["Validate the prompt before queueing: every link target/source id must exist as a key in prompt dict (frontend does this; scripts often don't).","Fix typos in node ids in hand-constructed API payloads.","If using cached/mutated history prompts, rebuild the full prompt rather than surgically editing link ids.","For custom-node authors calling get_node(), check has_node(id) first or keep ids from the same dynprompt generation."],"exampleFix":"# before\nprompt = {\n  '1': {'class_type': 'KSampler', 'inputs': {'model': ['99', 0], ...}},  # node '99' absent\n}\n\n# after\nprompt = {\n  '1': {'class_type': 'KSampler', 'inputs': {'model': ['2', 0], ...}},\n  '2': {'class_type': 'CheckpointLoaderSimple', 'inputs': {...}},\n}","handlingStrategy":"validation","validationCode":"def prompt_links_resolve(prompt: dict) -> bool:\n    for node_id, node in prompt.items():\n        for v in node.get('inputs', {}).values():\n            if isinstance(v, list) and len(v) == 2 and isinstance(v[0], str):\n                if v[0] not in prompt:\n                    return False\n    return True","typeGuard":null,"tryCatchPattern":"from comfy_execution.graph import NodeNotFoundError\ntry:\n    node = dynprompt.get_node(nid)\nexcept NodeNotFoundError as e:\n    logging.warning('stale node reference %s: %s', nid, e)\n    return","preventionTips":["Validate all link endpoints exist as prompt keys before queueing.","Avoid mutating a queued prompt's node ids from another thread/client.","When editing history prompts, regenerate the full dict rather than patching links."],"tags":["execution","graph","prompt","api"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}