{"record":{"id":"b07e8304427ada11","repo":"keras-team/keras","slug":"cannot-do-batch-dot-on-inputs-with-rank-2-recei-b07e83","errorCode":null,"errorMessage":"Cannot do batch_dot on inputs with rank < 2. Received inputs with tf.shapes {x_shape} and {y_shape}.","messagePattern":"Cannot do batch_dot on inputs with rank < 2\\. Received inputs with tf\\.shapes (.+?) and (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/legacy/backend.py","lineNumber":69,"sourceCode":"    if stop is None and start < 0:\n        start = 0\n    result = tf.range(start, limit=stop, delta=step, name=\"arange\")\n    if dtype != \"int32\":\n        result = tf.cast(result, dtype)\n    return result\n\n\n@keras_export(\"keras._legacy.backend.batch_dot\")\ndef batch_dot(x, y, axes=None):\n    \"\"\"DEPRECATED.\"\"\"\n    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]","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/legacy/backend.py#L51-L87","documentation":"The legacy keras backend batch_dot operation performs a batched dot product, which needs a batch axis plus at least one feature axis per operand — rank >= 2 for both x and y. Inputs of rank 0 or 1 (scalars or vectors) have no batch dimension to align, so the function raises before computing anything.","triggerScenarios":"Calling batch_dot with a 1D vector (shape (n,)) or scalar on either side; forgetting to expand dims on per-sample vectors before dotting; passing the output of a squeeze that removed the batch axis.","commonSituations":"Computing per-sample cosine similarity on 1D embeddings without expanding dims; using old keras.backend.batch_dot code from Keras 2 in Keras 3; squeezing tensors for logging then reusing them in a loss.","solutions":["Expand dims to restore the batch axis: x = keras.ops.expand_dims(x, 0) (or axis=-1 for a feature axis) so both operands are >= 2D","For plain vector/matrix products without a batch axis, use keras.ops.dot or matmul instead","Audit squeeze() calls whose results feed into batch_dot"],"exampleFix":"# before\nscore = keras.ops.batch_dot(vec_a, vec_b)  # both shape (128,)\n\n# after\nscore = keras.ops.batch_dot(keras.ops.expand_dims(vec_a, 0), keras.ops.expand_dims(vec_b, 0))","handlingStrategy":"validation","validationCode":"if len(x.shape) < 2:\n    x = keras.ops.expand_dims(x, 0)\nif len(y.shape) < 2:\n    y = keras.ops.expand_dims(y, 0)\nout = keras.ops.batch_dot(x, y)","typeGuard":"def is_rank2_plus(t) -> bool:\n    return len(t.shape) >= 2","tryCatchPattern":null,"preventionTips":["Expand dims on vectors before batch-level dot products","Prefer keras.ops.dot or matmul when no batch axis is involved"],"tags":["keras","batch-dot","tensor-rank","legacy-backend"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}