{"record":{"id":"a8f00cc3a75eb47f","repo":"invoke-ai/InvokeAI","slug":"call-saved-workflow-does-not-yet-support-child-wor","errorCode":null,"errorMessage":"call_saved_workflow does not yet support child workflows that mix supported batch nodes with unrelated generator nodes: {unsupported_nodes}","messagePattern":"call_saved_workflow does not yet support child workflows that mix supported batch nodes with unrelated generator nodes: (.+?)","errorType":"exception","errorClass":"UnsupportedWorkflowNodeError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/session_processor/workflow_call_batch.py","lineNumber":188,"sourceCode":"\n    unrelated_generator_nodes: list[tuple[str, str]] = []\n    for node in workflow_nodes:\n        if not _is_invocation_node(node):\n            continue\n\n        node_data = node[\"data\"]\n        node_id = node_data.get(\"id\")\n        node_type = node_data.get(\"type\")\n        if not isinstance(node_id, str) or not isinstance(node_type, str):\n            continue\n        if node_type.endswith(\"_generator\") and node_id not in used_generator_node_ids:\n            unrelated_generator_nodes.append((node_type, node_id))\n\n    if unrelated_generator_nodes:\n        unsupported_nodes = \", \".join(\n            f\"'{node_type}' (node '{node_id}')\" for node_type, node_id in unrelated_generator_nodes\n        )\n        raise UnsupportedWorkflowNodeError(\n            \"call_saved_workflow does not yet support child workflows that mix supported batch nodes with \"\n            f\"unrelated generator nodes: {unsupported_nodes}\"\n        )\n\n\ndef _get_batch_group_id(node_data: Mapping[str, Any]) -> str:\n    inputs = node_data.get(\"inputs\")\n    if not _is_mapping(inputs):\n        return \"None\"\n    batch_group_input = inputs.get(\"batch_group_id\")\n    if not _is_mapping(batch_group_input):\n        return \"None\"\n    batch_group_id = batch_group_input.get(\"value\")\n    if not isinstance(batch_group_id, str):\n        return \"None\"\n    if batch_group_id not in SUPPORTED_BATCH_GROUP_IDS:\n        raise UnsupportedWorkflowNodeError(f\"Unsupported batch group id '{batch_group_id}' in called workflow\")\n    return batch_group_id","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/session_processor/workflow_call_batch.py#L170-L206","documentation":"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.","triggerScenarios":"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.","commonSituations":"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'.","solutions":["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","Split the workflow into two: one batch-child workflow and one normal workflow containing the standalone generator","Replace the standalone generator node with a literal/default input on the consuming node","If you own the caller, pre-scan the workflow for generator nodes not feeding batch nodes and reject early with a clearer message"],"exampleFix":"// before: string_generator connected only to a prompt node, plus an integer_batch node fed from another generator\n// after: route the generator through the batch node\n//   integer_generator -> integer_batch (collection) -> downstream consumer\n//   (or delete the standalone generator and hardcode its value)","handlingStrategy":"validation","validationCode":"def has_unrelated_generators(workflow: dict) -> list[str]:\n    batch_types = {\"image_batch\", \"string_batch\", \"integer_batch\", \"float_batch\"}\n    nodes = [n for n in workflow.get(\"nodes\", []) if isinstance(n, dict) and n.get(\"type\") == \"invocation\"]\n    if not any(n.get(\"data\", {}).get(\"type\") in batch_types for n in nodes):\n        return []\n    # a generator is 'used' only if it directly sources a batch node field input\n    gen_node_ids = {n[\"data\"][\"id\"] for n in nodes if n[\"data\"].get(\"type\", \"\").endswith(\"_generator\")}\n    used = set()\n    for n in nodes:\n        if n[\"data\"].get(\"type\") not in batch_types:\n            continue\n        for e in workflow.get(\"edges\", []):\n            if e.get(\"target\") == n[\"data\"][\"id\"] and e.get(\"source\") in gen_node_ids:\n                used.add(e[\"source\"])\n    return sorted(gen_node_ids - used)","typeGuard":"def is_invocation_node(node: object) -> bool:\n    return isinstance(node, dict) and node.get(\"type\") == \"invocation\" and isinstance(node.get(\"data\"), dict)","tryCatchPattern":"from invokeai.app.services.shared.workflow_graph_builder import UnsupportedWorkflowNodeError\ntry:\n    children = build_batch_child_workflow_session_results(...)\nexcept UnsupportedWorkflowNodeError as e:\n    if \"unrelated generator nodes\" in str(e):\n        # surface which nodes to fix to the user\n        log.warning(str(e))\n    raise","preventionTips":["Keep generator nodes in called child workflows connected only through batch nodes","Pre-scan saved workflows for *_generator nodes before calling call_saved_workflow","Split mixed batch/generator workflows into separate workflows","After canvas edits, re-export and lint the workflow JSON"],"tags":["workflow","batch","unsupported-node","invokeai"],"backgroundTag":"unsupported-workflow-node","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}