keras-team/keras · error · ValueError

Cannot do batch_dot on inputs with tf.shapes {x_shape} and {

Error message

Cannot do batch_dot on inputs with tf.shapes {x_shape} and {y_shape} with axes={axes}. x.shape[%d] != y.shape[%d] (%d != %d).

What it means

batch_dot() requires the dimension of x selected by axes[0] to equal the dimension of y selected by axes[1]; a batched dot product is only defined for matching contraction sizes. When both static shapes are known and disagree, Keras raises this before touching the graph. The message prints both shapes and the axes so the mismatch can be located by inspection.

Source

Thrown at keras/src/legacy/backend.py:124

    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.
    orig_x_ndim = x_ndim
    orig_y_ndim = y_ndim

    # if rank is 2, expand to 3.
    if x_ndim == 2:
        x = tf.expand_dims(x, 1)
        a0 += 1
        x_ndim += 1
    if y_ndim == 2:
        y = tf.expand_dims(y, 2)
        y_ndim += 1

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Make the contracted dimensions equal: adjust the preceding Dense/kernel so x.shape[axes[0]] == y.shape[axes[1]]
  2. Re-check the axes argument — often you want axes=(2,1) or a transpose on one operand rather than the default
  3. Add/verify a projection layer (Dense to the common size) on the mismatched operand

Example fix

// before
out = K.batch_dot(q, k)  # q:(8,16), k:(8,32) -> ValueError

// after
k_proj = keras.layers.Dense(16)(k)
out = K.batch_dot(q, k_proj)
Defensive patterns

Strategy: validation

Validate before calling

assert x.shape[axes[0]] is None or y.shape[axes[1]] is None or x.shape[axes[0]] == y.shape[axes[1]], f'{x.shape} vs {y.shape} on axes {axes}'

Type guard

def compatible_batch_dot(x, y, axes=(1, 1)) -> bool:
    d1, d2 = x.shape[axes[0]], y.shape[axes[1]]
    return d1 is None or d2 is None or d1 == d2

Try / catch

except ValueError as e:
    if 'x.shape' in str(e):
        raise ValueError(f'contraction dims mismatch — project one side: {e}') from e
    raise

Prevention

When it happens

Trigger: batch_dot(x, y, axes=(i, j)) where x.shape[i] != y.shape[j], e.g. x shape (8, 16) dotted with y shape (8, 32) on default axes (1, 1) — contracting 16 against 32.

Common situations: Attention layers where query/key feature sizes differ (e.g. after a projection); hand-written merge layers ported from old Keras; transposition mistakes where one operand needs transpose_b or axes=(2,1).

Related errors


AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25). Data as JSON: /api/errors/f85c35b3c9245eed. Report an issue: GitHub.