{"record":{"id":"b9ac6590d51deefd","repo":"keras-team/keras","slug":"cannot-merge-tensors-with-different-batch-sizes-r","errorCode":null,"errorMessage":"Cannot merge tensors with different batch sizes. Received tensors with shapes {input_shape}","messagePattern":"Cannot merge tensors with different batch sizes\\. Received tensors with shapes (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/layers/merging/base_merge.py","lineNumber":117,"sourceCode":"\n    def build(self, input_shape):\n        # Used purely for shape validation.\n        if not isinstance(input_shape[0], (tuple, list)):\n            raise ValueError(\n                \"A merge layer should be called on a list of inputs. \"\n                f\"Received: input_shape={input_shape} (not a list of shapes)\"\n            )\n        if len(input_shape) < 1:\n            raise ValueError(\n                \"A merge layer should be called \"\n                \"on a list of at least 1 input. \"\n                f\"Received {len(input_shape)} inputs. \"\n                f\"Full input_shape received: {input_shape}\"\n            )\n\n        batch_sizes = {s[0] for s in input_shape if s} - {None}\n        if len(batch_sizes) > 1:\n            raise ValueError(\n                \"Cannot merge tensors with different batch sizes. \"\n                f\"Received tensors with shapes {input_shape}\"\n            )\n\n        if input_shape[0] is None:\n            output_shape = None\n        else:\n            output_shape = input_shape[0][1:]\n\n        for i in range(1, len(input_shape)):\n            if input_shape[i] is None:\n                shape = None\n            else:\n                shape = input_shape[i][1:]\n            output_shape = self._compute_elemwise_op_output_shape(\n                output_shape, shape\n            )\n","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/layers/merging/base_merge.py#L99-L135","documentation":"Merge layers require all input tensors to share the same batch dimension (None wildcard allowed). build() collects the first element of each input shape and raises if more than one distinct non-None batch size appears, because element-wise merging across different batch sizes is undefined.","triggerScenarios":"Calling Add()([x, y]) where x has batch size 32 and y has batch size 64; merging a fixed-batch Input with a dynamic-batch Input is allowed, but 32 vs 64 fails.","commonSituations":"Hardcoded batch dimensions in Input(shape=..., batch_size=32) mixing with dynamic batches; slicing one branch to a different number of samples; data pipelines producing mismatched batch sizes across modalities.","solutions":["Make batch dimensions consistent: use None (dynamic) batch in all Input definitions","Slice or pad one tensor so both have the same number of samples per batch","Remove batch_size=... hardcoding on Inputs feeding the merge"],"exampleFix":"# before\na = keras.Input(shape=(16,), batch_size=32)\nb = keras.Input(shape=(16,))  # runtime batch 64\nout = layers.Add()([a, b])  # ValueError\n\n# after\na = keras.Input(shape=(16,))\nout = layers.Add()([a, b])","handlingStrategy":"validation","validationCode":"batch_sizes = {tuple(t.shape)[0] for t in inputs if len(t.shape)} - {None}\nassert len(batch_sizes) <= 1, f'conflicting batch sizes: {batch_sizes}'","typeGuard":"def same_batch_size(shapes) -> bool:\n    bs = {s[0] for s in shapes if s} - {None}\n    return len(bs) <= 1","tryCatchPattern":null,"preventionTips":["Prefer dynamic (None) batch dimensions in Input definitions","Verify dataset batch sizes across modalities before merging","Avoid hardcoding batch_size when downstream merges exist"],"tags":["keras","merge","batch-size","shape-mismatch"],"backgroundTag":"batch-size-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}