keras-team/keras · error · ValueError
Cannot perform batch_dot over axis 0. If your inputs are not
Error message
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)
What it means
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.
Source
Thrown at keras/src/legacy/backend.py:113
if py_any(isinstance(a, (list, tuple)) for a in axes):
raise ValueError(
"Multiple target dimensions are not supported. "
"Expected: None, int, (int, int), "
f"Provided: {axes}"
)
# if tuple, convert to list.
axes = list(axes)
# convert negative indices.
if axes[0] < 0:
axes[0] += x_ndim
if axes[1] < 0:
axes[1] += y_ndim
# sanity checks
if 0 in axes:
raise ValueError(
"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)"
)
a0, a1 = axes
d1 = x_shape[a0]
d2 = y_shape[a1]
if d1 is not None and d2 is not None and d1 != d2:
raise ValueError(
"Cannot do batch_dot on inputs with tf.shapes "
f"{x_shape} and {y_shape} with axes={axes}. "
"x.shape[%d] != y.shape[%d] (%d != %d)."
% (axes[0], axes[1], d1, d2)
)
# backup ndims. Need them later.View on GitHub (pinned to 7a34a03db6)
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
Example fix
// before K.batch_dot(vec_a, vec_b, axes=0) # ValueError: axis 0 is batch // after import keras a = keras.ops.expand_dims(vec_a, 0) b = keras.ops.expand_dims(vec_b, 0) out = keras.ops.squeeze(keras.ops.matmul(a, b, transpose_b=True), 0)
Defensive patterns
Strategy: validation
Validate before calling
def safe_batch_dot_args(x, y, axes):
axes = list(axes)
if axes[0] < 0: axes[0] += len(x.shape)
if axes[1] < 0: axes[1] += len(y.shape)
assert 0 not in axes, 'axis 0 is the batch axis; expand dims or pick axes >= 1' Type guard
def is_batched(t) -> bool:
return t.ndim >= 2 # batch_dot needs a batch dim plus >=1 feature dim Try / catch
except ValueError as e:
if 'axis 0' in str(e):
x = keras.ops.expand_dims(x, 0); y = keras.ops.expand_dims(y, 0)
out = K.batch_dot(x, y, axes=axes)
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Cannot do batch_dot on inputs with tf.shapes {x_shape} and {
- Architecture configuration does not match {weights_name} var
- Model name "{name}" does not match weights variant "{weights
- DenseNet does not support the `channels_first` image data fo
- The TFSMLayer is only currently supported with the TensorFlo
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/0be920850f4eca86.
Report an issue: GitHub.