{"record":{"id":"6917f11b4598bf9e","repo":"invoke-ai/InvokeAI","slug":"call-saved-workflow-batch-child-workflow-node-no","errorCode":null,"errorMessage":"call_saved_workflow batch child workflow node '{node_data.get('id')}' must provide a direct list for '{field_name}'","messagePattern":"call_saved_workflow batch child workflow node '(.+?)' must provide a direct list for '(.+?)'","errorType":"exception","errorClass":"UnsupportedWorkflowNodeError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/session_processor/workflow_call_batch.py","lineNumber":220,"sourceCode":"    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}\"'))\n    except Exception:\n        return input_value.split(split_on)\n\n\ndef _resolve_float_generator(value: Mapping[str, Any]) -> list[float]:\n    generator_type = value.get(\"type\")\n    if generator_type == \"float_generator_arithmetic_sequence\":\n        start = float(value.get(\"start\", 0))","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/session_processor/workflow_call_batch.py#L202-L238","documentation":"The batch node's field input exists but its value is not a plain JSON list. Batch expansion requires the batch node to provide a direct array of items (the 'value' inside the input mapping must be a list); nested references, objects, or scalar values are rejected because there is nothing iterable to expand into child sessions.","triggerScenarios":"Calling a saved workflow where e.g. string_batch.inputs.strings.value is a string, an object, or null instead of a list — for instance someone stored {\"value\": \"a,b,c\"} expecting it to be split.","commonSituations":"Hand-editing workflow JSON and giving a scalar instead of an array; expecting comma-separated strings or nested batch configs to work; programmatic workflow generation with wrong value shape.","solutions":["Set the input's value to a direct JSON list, e.g. {\"value\": [\"a\", \"b\"]}","Pre-split delimited values yourself (or use a *_parse_string generator node wired to the batch input)","Re-export the workflow from the canvas so values get the correct list shape","Validate workflow JSON against the InvokeAI node schema before calling"],"exampleFix":"// before\n\"strings\": { \"value\": \"a,b,c\" }\n// after\n\"strings\": { \"value\": [\"a\", \"b\", \"c\"] }","handlingStrategy":"validation","validationCode":"BATCH_FIELD_NAMES = {\"image_batch\": \"images\", \"string_batch\": \"strings\", \"integer_batch\": \"integers\", \"float_batch\": \"floats\"}\nfor node in workflow.get(\"nodes\", []):\n    d = node.get(\"data\", {}) if isinstance(node, dict) else {}\n    field = BATCH_FIELD_NAMES.get(d.get(\"type\"))\n    inp = d.get(\"inputs\", {}).get(field) if isinstance(d.get(\"inputs\"), dict) else None\n    if isinstance(inp, dict) and not isinstance(inp.get(\"value\"), list):\n        raise ValueError(f\"batch node {d.get('id')} field '{field}' value must be a list\")","typeGuard":"def is_direct_list_batch_value(inp: object) -> bool:\n    return isinstance(inp, dict) and isinstance(inp.get(\"value\"), list)","tryCatchPattern":"try:\n    sessions = build_batch_child_workflow_sessions(...)\nexcept UnsupportedWorkflowNodeError as e:\n    if \"must provide a direct list\" in str(e):\n        workflow = coerce_batch_values_to_lists(workflow)  # wrap scalars in lists / split strings\n        sessions = build_batch_child_workflow_sessions(...)\n    else:\n        raise","preventionTips":["Always encode batch values as JSON arrays, even for a single item","Pre-split delimited strings yourself or use a *_parse_string generator","Type-check batch values in your workflow generation code","Round-trip workflow JSON through pydantic models before calling"],"tags":["workflow","batch","type-error","invokeai"],"backgroundTag":"schema-validation-failed","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}