{"record":{"id":"c317a302d6c4bfc0","repo":"keras-team/keras","slug":"cannot-do-batch-dot-on-inputs-with-different-batch-c317a3","errorCode":null,"errorMessage":"Cannot do batch_dot on inputs with different batch sizes. Received inputs with tf.shapes {x_shape} and {y_shape}.","messagePattern":"Cannot do batch_dot on inputs with different batch sizes\\. Received inputs with tf\\.shapes (.+?) and (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/legacy/backend.py","lineNumber":80,"sourceCode":"    x_shape = x.shape\n    y_shape = y.shape\n\n    x_ndim = len(x_shape)\n    y_ndim = len(y_shape)\n\n    if x_ndim < 2 or y_ndim < 2:\n        raise ValueError(\n            \"Cannot do batch_dot on inputs \"\n            \"with rank < 2. \"\n            f\"Received inputs with tf.shapes {x_shape} and {y_shape}.\"\n        )\n\n    x_batch_size = x_shape[0]\n    y_batch_size = y_shape[0]\n\n    if x_batch_size is not None and y_batch_size is not None:\n        if x_batch_size != y_batch_size:\n            raise ValueError(\n                \"Cannot do batch_dot on inputs \"\n                \"with different batch sizes. \"\n                \"Received inputs with tf.shapes \"\n                f\"{x_shape} and {y_shape}.\"\n            )\n    if isinstance(axes, int):\n        axes = [axes, axes]\n\n    if axes is None:\n        if y_ndim == 2:\n            axes = [x_ndim - 1, y_ndim - 1]\n        else:\n            axes = [x_ndim - 1, y_ndim - 2]\n\n    if py_any(isinstance(a, (list, tuple)) for a in axes):\n        raise ValueError(\n            \"Multiple target dimensions are not supported. \"\n            \"Expected: None, int, (int, int), \"","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/legacy/backend.py#L62-L98","documentation":"batch_dot pairs each sample i of x with sample i of y, so the leading (batch) dimensions of both operands must match when both are known. The function compares x.shape[0] and y.shape[0] and raises when they differ, preventing silent misalignment or accidental broadcasting.","triggerScenarios":"Calling batch_dot(x, y) where x has shape (32, d) and y has shape (64, d); mixing tensors from different batches or from a split/reshuffle; broadcasting one operand across the batch unintentionally.","commonSituations":"Contrastive/triplet loss code where positives were sampled with a different batch size; last partial batch in a generator vs a fixed-size target tensor; splitting tensors and losing track of batch size; reusing a cached tensor from another batch.","solutions":["Align batch sizes: slice or pad the larger tensor so shape[0] matches (e.g. y = y[: x.shape[0]])","Recompute both operands from the same batch instead of caching one","Use drop_remainder=True in your data pipeline so all batches have equal size"],"exampleFix":"# before\nloss = keras.ops.batch_dot(embeddings, targets)  # (32, d) vs (64, d)\n\n# after\ntargets = targets[: embeddings.shape[0]]\nloss = keras.ops.batch_dot(embeddings, targets)","handlingStrategy":"validation","validationCode":"bx, by = x.shape[0], y.shape[0]\nif bx is not None and by is not None and bx != by:\n    n = min(bx, by)\n    x, y = x[:n], y[:n]\nout = keras.ops.batch_dot(x, y)","typeGuard":"def same_batch_size(x, y) -> bool:\n    return x.shape[0] is None or y.shape[0] is None or x.shape[0] == y.shape[0]","tryCatchPattern":null,"preventionTips":["Derive both operands from the same batch; avoid caching one side","Use drop_remainder=True so batch sizes are constant"],"tags":["keras","batch-dot","batch-size-mismatch","legacy-backend"],"backgroundTag":"batch-size-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}