{"record":{"id":"ba544ba345cd5103","repo":"invoke-ai/InvokeAI","slug":"call-saved-workflow-batch-child-workflow-node-inpu","errorCode":null,"errorMessage":"call_saved_workflow batch child workflow node inputs are malformed","messagePattern":"call_saved_workflow batch child workflow node inputs are malformed","errorType":"exception","errorClass":"UnsupportedWorkflowNodeError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/session_processor/workflow_call_batch.py","lineNumber":212,"sourceCode":"def _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\n\n\ndef _get_batch_items(node_data: Mapping[str, Any], field_name: str) -> list[Any]:\n    inputs = node_data.get(\"inputs\")\n    if not _is_mapping(inputs):\n        raise UnsupportedWorkflowNodeError(\"call_saved_workflow batch child workflow node inputs are malformed\")\n    batch_input = inputs.get(field_name)\n    if not _is_mapping(batch_input):\n        raise UnsupportedWorkflowNodeError(\n            f\"call_saved_workflow batch child workflow node is missing required '{field_name}' input\"\n        )\n    batch_items = batch_input.get(\"value\")\n    if not isinstance(batch_items, list):\n        raise UnsupportedWorkflowNodeError(\n            f\"call_saved_workflow batch child workflow node '{node_data.get('id')}' must provide a direct list for '{field_name}'\"\n        )\n    return batch_items\n\n\ndef _parse_split_values(input_value: str, split_on: str) -> list[str]:\n    if split_on == \"\":\n        return [input_value]\n    try:\n        return input_value.split(json.loads(f'\"{split_on}\"'))","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/session_processor/workflow_call_batch.py#L194-L230","documentation":"The batch node's data.inputs in the called child workflow is missing or not a mapping, so _get_batch_items cannot look up the batch field. InvokeAI requires each batch node's saved workflow JSON to contain a well-formed inputs dict; when it doesn't, expansion cannot proceed and raises UnsupportedWorkflowNodeError.","triggerScenarios":"Calling a saved workflow whose image_batch/string_batch/integer_batch/float_batch node has data.inputs absent, null, an array, or otherwise not a JSON object — typically because the node was not connected to a generator and its direct value path is being read.","commonSituations":"Hand-written or programmatically generated workflow JSON missing the inputs block; corrupt/truncated workflow export; a node type renamed/reshaped between InvokeAI versions leaving stale node data.","solutions":["Fix the workflow JSON so each batch node has data.inputs as an object containing the expected field (images/strings/integers/floats)","Re-export the workflow from the InvokeAI canvas rather than hand-editing","Connect the batch node's field input to a generator node so the direct-input path is never taken","Migrate/upgrade: check the InvokeAI changelog for node schema changes and re-save the workflow"],"exampleFix":"// before\n\"data\": { \"id\": \"abc\", \"type\": \"string_batch\" }\n// after\n\"data\": { \"id\": \"abc\", \"type\": \"string_batch\", \"inputs\": { \"strings\": { \"value\": [\"a\", \"b\"] } } }","handlingStrategy":"type-guard","validationCode":"def batch_nodes_have_inputs(workflow: dict) -> list[str]:\n    bad = []\n    for node in workflow.get(\"nodes\", []):\n        if isinstance(node, dict) and node.get(\"type\") == \"invocation\":\n            d = node.get(\"data\", {})\n            if d.get(\"type\") in {\"image_batch\", \"string_batch\", \"integer_batch\", \"float_batch\"} and not isinstance(d.get(\"inputs\"), dict):\n                bad.append(str(d.get(\"id\")))\n    return bad","typeGuard":"from collections.abc import Mapping\n\ndef has_valid_inputs(node: object) -> bool:\n    return (isinstance(node, dict) and isinstance(node.get(\"data\"), Mapping)\n            and isinstance(node[\"data\"].get(\"inputs\"), Mapping))","tryCatchPattern":"try:\n    sessions = build_batch_child_workflow_sessions(...)\nexcept UnsupportedWorkflowNodeError as e:\n    if \"node inputs are malformed\" in str(e):\n        workflow = reexport_workflow_from_canvas(workflow_id)  # regenerate correct JSON\n        sessions = build_batch_child_workflow_sessions(...)\n    else:\n        raise","preventionTips":["Export workflows from the InvokeAI canvas instead of hand-writing JSON","Validate node schemas (pydantic) before submitting workflows","Beware of schema changes across InvokeAI versions — re-save old workflows","Keep programmatic workflow builders aligned with node data shapes"],"tags":["workflow","batch","schema","invokeai"],"backgroundTag":"schema-validation-failed","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}