{"record":{"id":"b349586386f93508","repo":"invoke-ai/InvokeAI","slug":"zipped-batch-items-must-all-have-the-same-length","errorCode":null,"errorMessage":"Zipped batch items must all have the same length","messagePattern":"Zipped batch items must all have the same length","errorType":"validation","errorClass":"BatchZippedLengthError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/session_queue/session_queue_common.py","lineNumber":102,"sourceCode":"    )\n    data: Optional[BatchDataCollection] = Field(default=None, description=\"The batch data collection.\")\n    graph: Graph = Field(description=\"The graph to initialize the session with\")\n    workflow: Optional[WorkflowWithoutID] = Field(\n        default=None, description=\"The workflow to initialize the session with\"\n    )\n    runs: int = Field(\n        default=1, ge=1, description=\"Int stating how many times to iterate through all possible batch indices\"\n    )\n\n    @field_validator(\"data\")\n    def validate_lengths(cls, v: Optional[BatchDataCollection]):\n        if v is None:\n            return v\n        for batch_data_list in v:\n            first_item_length = len(batch_data_list[0].items) if batch_data_list and batch_data_list[0].items else 0\n            for i in batch_data_list:\n                if len(i.items) != first_item_length:\n                    raise BatchZippedLengthError(\"Zipped batch items must all have the same length\")\n        return v\n\n    @field_validator(\"data\")\n    def validate_types(cls, v: Optional[BatchDataCollection]):\n        if v is None:\n            return v\n        for batch_data_list in v:\n            for datum in batch_data_list:\n                if not datum.items:\n                    continue\n\n                # Special handling for numbers - they can be mixed\n                # TODO(psyche): Update BatchDatum to have a `type` field to specify the type of the items, then we can have strict float and int fields\n                if all(isinstance(item, (int, float)) for item in datum.items):\n                    continue\n\n                # Get the type of the first item in the list\n                first_item_type = type(datum.items[0])","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/session_queue/session_queue_common.py#L84-L120","documentation":"When a batch uses collect-type 'zip' (BatchZipped), every batch_data list must contain item lists of equal length so items can be paired index-by-index. The BatchZippedLengthError is raised by the validate_lengths field validator when any list's item count differs from the first list's count.","triggerScenarios":"Building a Batch configuration with data collections where e.g. one image collection has 4 items and a paired prompt collection has 3 items, then validating/enqueuing the batch session.","commonSituations":"Hand-editing batch JSON, generating batch data from arrays of unequal length in a script, or appending items to one collection but not its zip partner.","solutions":["Pad or trim collections so every zipped batch_data list has the same number of items","Check the script generating the batch data for off-by-one or filtering differences between collections","Switch the batch data to 'unzip' collect type if independent expansion is intended","Validate item counts client-side before creating the Batch"],"exampleFix":"// before\n{\"collect\": \"zip\", \"items\": [\"p1\", \"p2\", \"p3\"]} paired with 4 images\n// after: lengths must match\n{\"collect\": \"zip\", \"items\": [\"p1\", \"p2\", \"p3\"]} paired with 3 images","handlingStrategy":"validation","validationCode":"def validate_zip_lengths(data):\n    for batch_data_list in data:\n        lengths = {len(d.items) for d in batch_data_list if d.items}\n        if len(lengths) > 1:\n            raise ValueError(f\"Zipped batch collections must have equal lengths, got {sorted(lengths)}.\")","typeGuard":"def is_zip_safe(batch_data_list) -> bool:\n    lengths = {len(d.items) for d in batch_data_list if d.items}\n    return len(lengths) <= 1","tryCatchPattern":"try:\n    batch = Batch(**batch_dict)\nexcept BatchZippedLengthError as e:\n    logger.error(f\"Zip length mismatch: {e}\")\n    # pad/trim collections and rebuild","preventionTips":["Assert len(a.items) == len(b.items) for every zip pair in generation scripts","Generate paired collections from a single source list to keep them in sync","Prefer 'unzip' collect type when pairing is not intended","Validate batch JSON before enqueueing"],"tags":["batch","validation","pydantic"],"backgroundTag":"batch-zip-length-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}