invoke-ai/InvokeAI · error · InvalidWorkflowInputError

call_saved_workflow input

Error message

call_saved_workflow input '{input_name}' targets invalid child workflow inputs on '{node_id}'

What it means

The matched node's 'inputs' member is not a mapping (dict), so the builder cannot insert the dynamic input value. The saved workflow's node data is malformed even though the node type and field validated.

Solutions

  1. Fix the node's 'inputs' to be a dict keyed by field name (re-export from the editor).
  2. Re-save the workflow via the UI so the SDK serializes inputs correctly.
  3. Validate the workflow document (inputs mapping per node) before calling apply_workflow_inputs_to_workflow.

Example fix

// before
"inputs": ["prompt"]
// after
"inputs": {"prompt": {"value": "a cat"}}
Defensive patterns

Strategy: type-guard

Validate before calling

def node_inputs_are_mapping(workflow: dict, node_id: str) -> bool:
    node = next((n for n in workflow.get("nodes", []) if isinstance(n, dict) and n.get("id") == node_id), None)
    return isinstance(node, dict) and isinstance(node.get("data", {}).get("inputs"), dict)

Type guard

def has_mapping_inputs(node: dict) -> bool:
    data = node.get("data") if isinstance(node, dict) else None
    return isinstance(data, dict) and isinstance(data.get("inputs"), dict)

Try / catch

try:
    apply_workflow_inputs_to_workflow(workflow, workflow_inputs)
except InvalidWorkflowInputError as e:
    if "invalid child workflow inputs" in str(e):
        log.error("node inputs malformed in saved workflow: %s", e)
        raise ValueError("Fix or re-export the workflow; node inputs must be a dict") from e
    raise

Prevention

When it happens

Trigger: apply_workflow_inputs_to_workflow: matching_node_data.setdefault("inputs", {}) returns a value for which _is_mapping(inputs) is False.

Common situations: Hand-edited workflow JSON where 'inputs' is a list or string; exports from other tools using a different inputs representation; truncated or programmatically corrupted workflow documents.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/986f0a92d8727dc0. Report an issue: GitHub.

Appendix: source

Thrown at invokeai/app/services/shared/workflow_graph_builder.py:158

        )
        if matching_node is None:
            raise InvalidWorkflowInputError(
                f"call_saved_workflow input '{input_name}' targets missing child workflow node '{node_id}'"
            )
        matching_node_data = matching_node["data"]
        node_type = matching_node_data.get("type")
        if not isinstance(node_type, str):
            raise InvalidWorkflowInputError(
                f"call_saved_workflow input '{input_name}' targets missing child workflow node '{node_id}'"
            )
        invocation_class = InvocationRegistry.get_invocation_for_type(node_type)
        if invocation_class is None or field_name not in invocation_class.model_fields:
            raise InvalidWorkflowInputError(
                f"call_saved_workflow input '{input_name}' targets missing child workflow field '{field_name}'"
            )
        inputs = matching_node_data.setdefault("inputs", {})
        if not _is_mapping(inputs):
            raise InvalidWorkflowInputError(
                f"call_saved_workflow input '{input_name}' targets invalid child workflow inputs on '{node_id}'"
            )
        inputs[field_name] = {"value": value}


def apply_workflow_inputs_to_graph(
    graph: Graph, workflow: Mapping[str, Any], workflow_inputs: Mapping[str, Any]
) -> None:
    if not workflow_inputs:
        return

    mutable_workflow = dict(workflow)
    apply_workflow_inputs_to_workflow(mutable_workflow, workflow_inputs)
    for input_name, value in workflow_inputs.items():
        node_id, field_name = parse_call_saved_workflow_dynamic_input(input_name)
        node = graph.nodes.get(node_id)
        if node is None:
            continue

View on GitHub (pinned to 0b6a024f2f)