invoke-ai/InvokeAI · error · UnsupportedWorkflowNodeError

call_saved_workflow does not yet support child workflows tha

Error message

call_saved_workflow does not yet support child workflows that mix supported batch nodes with unrelated generator nodes: {unsupported_nodes}

What it means

When a called (child) workflow contains supported batch nodes (image_batch/string_batch/integer_batch/float_batch), InvokeAI expands them into child sessions. Every *_generator node in that workflow must be one that actually feeds one of those batch nodes; any leftover generator node not consumed by a batch node is rejected, because the batch expansion machinery cannot expand or sanitize it. This is a deliberate guard in _reject_unrelated_generator_nodes, not a data corruption problem.

Source

Thrown at invokeai/app/services/session_processor/workflow_call_batch.py:188

    unrelated_generator_nodes: list[tuple[str, str]] = []
    for node in workflow_nodes:
        if not _is_invocation_node(node):
            continue

        node_data = node["data"]
        node_id = node_data.get("id")
        node_type = node_data.get("type")
        if not isinstance(node_id, str) or not isinstance(node_type, str):
            continue
        if node_type.endswith("_generator") and node_id not in used_generator_node_ids:
            unrelated_generator_nodes.append((node_type, node_id))

    if unrelated_generator_nodes:
        unsupported_nodes = ", ".join(
            f"'{node_type}' (node '{node_id}')" for node_type, node_id in unrelated_generator_nodes
        )
        raise UnsupportedWorkflowNodeError(
            "call_saved_workflow does not yet support child workflows that mix supported batch nodes with "
            f"unrelated generator nodes: {unsupported_nodes}"
        )


def _get_batch_group_id(node_data: Mapping[str, Any]) -> str:
    inputs = node_data.get("inputs")
    if not _is_mapping(inputs):
        return "None"
    batch_group_input = inputs.get("batch_group_id")
    if not _is_mapping(batch_group_input):
        return "None"
    batch_group_id = batch_group_input.get("value")
    if not isinstance(batch_group_id, str):
        return "None"
    if batch_group_id not in SUPPORTED_BATCH_GROUP_IDS:
        raise UnsupportedWorkflowNodeError(f"Unsupported batch group id '{batch_group_id}' in called workflow")
    return batch_group_id

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Remove the unrelated generator node from the workflow, or connect it through a batch node (e.g. wire it into a string_batch/integer_batch input) so it becomes a used generator
  2. Split the workflow into two: one batch-child workflow and one normal workflow containing the standalone generator
  3. Replace the standalone generator node with a literal/default input on the consuming node
  4. If you own the caller, pre-scan the workflow for generator nodes not feeding batch nodes and reject early with a clearer message

Example fix

// before: string_generator connected only to a prompt node, plus an integer_batch node fed from another generator
// after: route the generator through the batch node
//   integer_generator -> integer_batch (collection) -> downstream consumer
//   (or delete the standalone generator and hardcode its value)
Defensive patterns

Strategy: validation

Validate before calling

def has_unrelated_generators(workflow: dict) -> list[str]:
    batch_types = {"image_batch", "string_batch", "integer_batch", "float_batch"}
    nodes = [n for n in workflow.get("nodes", []) if isinstance(n, dict) and n.get("type") == "invocation"]
    if not any(n.get("data", {}).get("type") in batch_types for n in nodes):
        return []
    # a generator is 'used' only if it directly sources a batch node field input
    gen_node_ids = {n["data"]["id"] for n in nodes if n["data"].get("type", "").endswith("_generator")}
    used = set()
    for n in nodes:
        if n["data"].get("type") not in batch_types:
            continue
        for e in workflow.get("edges", []):
            if e.get("target") == n["data"]["id"] and e.get("source") in gen_node_ids:
                used.add(e["source"])
    return sorted(gen_node_ids - used)

Type guard

def is_invocation_node(node: object) -> bool:
    return isinstance(node, dict) and node.get("type") == "invocation" and isinstance(node.get("data"), dict)

Try / catch

from invokeai.app.services.shared.workflow_graph_builder import UnsupportedWorkflowNodeError
try:
    children = build_batch_child_workflow_session_results(...)
except UnsupportedWorkflowNodeError as e:
    if "unrelated generator nodes" in str(e):
        # surface which nodes to fix to the user
        log.warning(str(e))
    raise

Prevention

When it happens

Trigger: Calling a saved workflow via call_saved_workflow / build_batch_child_workflow_session_results where the workflow has at least one supported batch node AND contains a node whose type ends with '_generator' that is not the direct (or connector-resolved) source of that batch node's field input — e.g. a dangling string_generator wired only into a prompt node, not into the string_batch node.

Common situations: Editing a workflow in the canvas to add a generator (random integer, dynamic prompts) connected elsewhere in the graph while also keeping a batch node; importing a workflow that mixes batch and generator patterns; a generator edge was accidentally deleted so it is no longer 'used'.

Related errors


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