{"record":{"id":"0be920850f4eca86","repo":"keras-team/keras","slug":"cannot-perform-batch-dot-over-axis-0-if-your-inpu-0be920","errorCode":null,"errorMessage":"Cannot perform batch_dot over axis 0. If your inputs are not batched, add a dummy batch dimension to your inputs using K.expand_dims(x, 0)","messagePattern":"Cannot perform batch_dot over axis 0\\. If your inputs are not batched, add a dummy batch dimension to your inputs using K\\.expand_dims\\(x, 0\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/legacy/backend.py","lineNumber":113,"sourceCode":"    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), \"\n            f\"Provided: {axes}\"\n        )\n\n    # if tuple, convert to list.\n    axes = list(axes)\n\n    # convert negative indices.\n    if axes[0] < 0:\n        axes[0] += x_ndim\n    if axes[1] < 0:\n        axes[1] += y_ndim\n\n    # sanity checks\n    if 0 in axes:\n        raise ValueError(\n            \"Cannot perform batch_dot over axis 0. \"\n            \"If your inputs are not batched, \"\n            \"add a dummy batch dimension to your \"\n            \"inputs using K.expand_dims(x, 0)\"\n        )\n    a0, a1 = axes\n    d1 = x_shape[a0]\n    d2 = y_shape[a1]\n\n    if d1 is not None and d2 is not None and d1 != d2:\n        raise ValueError(\n            \"Cannot do batch_dot on inputs with tf.shapes \"\n            f\"{x_shape} and {y_shape} with axes={axes}. \"\n            \"x.shape[%d] != y.shape[%d] (%d != %d).\"\n            % (axes[0], axes[1], d1, d2)\n        )\n\n    # backup ndims. Need them later.","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/legacy/backend.py#L95-L131","documentation":"Keras' deprecated symbolic backend batch_dot() refuses to reduce over axis 0 because axis 0 is reserved as the batch dimension. After normalizing negative axes, if either requested axis resolves to 0 the operation is rejected. The error tells you the inputs are probably unbatched single samples.","triggerScenarios":"Calling keras._legacy.backend.batch_dot(x, y, axes=...) (or a legacy layer that routes to it) where the resolved axis for x or y is 0 — e.g. passing 2D tensors shaped (n, m) with axes=0, or a negative axis that normalizes to 0 for low-rank inputs.","commonSituations":"Porting Keras 1.x/2.x code that called dot()/batch_dot() on single (unbatched) vectors; feeding rank-1 or rank-2 tensors from numpy instead of batched rank-2+ tensors; custom attention layers migrated to the legacy backend namespace.","solutions":["Add a dummy batch dimension: x = keras.ops.expand_dims(x, 0) (or K.expand_dims(x, 0)) before calling batch_dot, then squeeze it from the result","Choose axes >= 1 that reference real feature dimensions instead of the batch axis","Migrate off keras._legacy.backend.batch_dot to keras.ops.matmul / keras.ops.einsum, which handle unbatched inputs explicitly"],"exampleFix":"// before\nK.batch_dot(vec_a, vec_b, axes=0)  # ValueError: axis 0 is batch\n\n// after\nimport keras\na = keras.ops.expand_dims(vec_a, 0)\nb = keras.ops.expand_dims(vec_b, 0)\nout = keras.ops.squeeze(keras.ops.matmul(a, b, transpose_b=True), 0)","handlingStrategy":"validation","validationCode":"def safe_batch_dot_args(x, y, axes):\n    axes = list(axes)\n    if axes[0] < 0: axes[0] += len(x.shape)\n    if axes[1] < 0: axes[1] += len(y.shape)\n    assert 0 not in axes, 'axis 0 is the batch axis; expand dims or pick axes >= 1'","typeGuard":"def is_batched(t) -> bool:\n    return t.ndim >= 2  # batch_dot needs a batch dim plus >=1 feature dim","tryCatchPattern":"except ValueError as e:\n    if 'axis 0' in str(e):\n        x = keras.ops.expand_dims(x, 0); y = keras.ops.expand_dims(y, 0)\n        out = K.batch_dot(x, y, axes=axes)\n    else:\n        raise","preventionTips":["Always feed batched (rank>=2) tensors to batch_dot","Prefer keras.ops.matmul/einsum in new code over keras._legacy.backend","Unit-test custom layers with both batched and single-sample inputs"],"tags":["keras","tensorflow","batch-dot","shape-mismatch"],"backgroundTag":"invalid-tensor-shape","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}