Comfy-Org/ComfyUI · error · NodeInputError

Node {to_node_id} says it needs input {to_input}, but that v

Error message

Node {to_node_id} says it needs input {to_input}, but that value is a constant

What it means

Raised as NodeInputError by TopologicalSort.make_input_strong_link() in comfy_execution/graph.py when the named input exists in the node's prompt 'inputs' but holds a constant value instead of a link. Strong links only make sense between nodes (link format is [from_node_id, from_socket], detected by is_link()); a widget value like a number or string cannot participate, so the engine refuses rather than fabricate a dependency.

Source

Thrown at comfy_execution/graph.py:126

        self.dynprompt = dynprompt
        self.pendingNodes = {}
        self.blockCount = {} # Number of nodes this node is directly blocked by
        self.blocking = {} # Which nodes are blocked by this node
        self.externalBlocks = 0
        self.unblockedEvent = asyncio.Event()

    def get_input_info(self, unique_id, input_name):
        class_type = self.dynprompt.get_node(unique_id)["class_type"]
        class_def = nodes.NODE_CLASS_MAPPINGS[class_type]
        return get_input_info(class_def, input_name)

    def make_input_strong_link(self, to_node_id, to_input):
        inputs = self.dynprompt.get_node(to_node_id)["inputs"]
        if to_input not in inputs:
            raise NodeInputError(f"Node {to_node_id} says it needs input {to_input}, but there is no input to that node at all")
        value = inputs[to_input]
        if not is_link(value):
            raise NodeInputError(f"Node {to_node_id} says it needs input {to_input}, but that value is a constant")
        from_node_id, from_socket = value
        self.add_strong_link(from_node_id, from_socket, to_node_id)

    def add_strong_link(self, from_node_id, from_socket, to_node_id):
        if not self.is_cached(from_node_id):
            self.add_node(from_node_id)
            if to_node_id not in self.blocking[from_node_id]:
                self.blocking[from_node_id][to_node_id] = {}
                self.blockCount[to_node_id] += 1
            self.blocking[from_node_id][to_node_id][from_socket] = True

    def add_node(self, node_unique_id, include_lazy=False, subgraph_nodes=None):
        node_ids = [node_unique_id]
        links = []

        while len(node_ids) > 0:
            unique_id = node_ids.pop()
            if unique_id in self.pendingNodes:

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Right-click the input on the target node and 'Convert widget to input', then connect the upstream node so the value arrives as a link.
  2. If you own the node, only declare strong dependencies for inputs that are meaningfully linkable, or tolerate constants by skipping the strong-link request.
  3. Rebuild the connection from the node the dependency expects (e.g. a primitive/seed node).
  4. Update or roll back the custom node pack if a new version made a formerly optional input mandatory.

Example fix

# before: prompt has a constant where a link is required
{'3': {'class_type': 'KSampler', 'inputs': {'seed': 42, ...}}}
# and node 3 declares a strong dependency on 'seed'

# after: route the value through a node
{'2': {'class_type': 'PrimitiveNode', 'inputs': {}},
 '3': {'class_type': 'KSampler', 'inputs': {'seed': ['2', 0], ...}}}
Defensive patterns

Strategy: type-guard

Validate before calling

def is_link(v) -> bool:
    return isinstance(v, list) and len(v) == 2 and isinstance(v[0], (str, int)) and isinstance(v[1], int)

if not is_link(prompt[nid]['inputs'][input_name]):
    raise ValueError(f'{input_name!r} must be connected to a node, not a constant')

Type guard

def is_link(v) -> bool:
    return isinstance(v, list) and len(v) == 2 and isinstance(v[0], (str, int)) and isinstance(v[1], int)

Try / catch

from comfy_execution.graph import NodeInputError
try:
    make_input_strong_link(nid, name)
except NodeInputError as e:
    raise UserVisibleError(f'Convert {name!r} to a node input: {e}') from e

Prevention

When it happens

Trigger: A node declares a strong dependency on an input (via CHECK_REQUIREMENTS / lazy input resolution) but the workflow has that input connected to a widget constant — e.g. 'seed' or 'denoise' typed directly instead of fed from another node. The dependency machinery calls make_input_strong_link, finds 1.0 or 'text' instead of a link array, and raises.

Common situations: Users convert a widget to input only when convenient and leave a constant where a node implementation now requires an upstream node (common with seeds fed from a 'seed generator' node or context nodes); custom nodes adding hard requirements to previously-constant inputs; workflows shared between users where one side used input conversion.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/324cbec05283eac2. Report an issue: GitHub.