keras-team/keras · error · ValueError

Multiple target dimensions are not supported. Expected: None

Error message

Multiple target dimensions are not supported. Expected: None, int, (int, int), Provided: {axes}

What it means

batch_dot accepts axes as None, an int, or an (int, int) pair; the legacy implementation rejects any axes spec containing a nested list/tuple (e.g. [x_ndim-1, [1, 2]]). Internally ints get normalized to a pair, but per-operand multi-axis targets are not supported by the underlying dot, so a nested sequence triggers this ValueError.

Source

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

    if x_batch_size is not None and y_batch_size is not None:
        if x_batch_size != y_batch_size:
            raise ValueError(
                "Cannot do batch_dot on inputs "
                "with different batch sizes. "
                "Received inputs with tf.shapes "
                f"{x_shape} and {y_shape}."
            )
    if isinstance(axes, int):
        axes = [axes, axes]

    if axes is None:
        if y_ndim == 2:
            axes = [x_ndim - 1, y_ndim - 1]
        else:
            axes = [x_ndim - 1, y_ndim - 2]

    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. "

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Contract one axis per operand: pass a flat pair like axes=(1, 1) and reshape beforehand to fold extra axes together
  2. For genuine multi-axis contraction, use tf.tensordot or keras.ops.einsum instead of batch_dot
  3. Normalize axes input to an int or (int, int) before calling

Example fix

# before
out = keras.ops.batch_dot(x, y, axes=[[1, 2], [1, 2]])

# after
x_flat = keras.ops.reshape(x, (-1, d1 * d2))
y_flat = keras.ops.reshape(y, (-1, d1 * d2))
out = keras.ops.batch_dot(x_flat, y_flat, axes=(1, 1))
Defensive patterns

Strategy: validation

Validate before calling

axes = (axes, axes) if isinstance(axes, int) else tuple(axes)
assert all(isinstance(a, int) for a in axes), f'axes must be int or (int, int), got {axes}'
out = keras.ops.batch_dot(x, y, axes=axes)

Type guard

def valid_batch_dot_axes(axes) -> bool:
    if axes is None or isinstance(axes, int):
        return True
    if isinstance(axes, (tuple, list)) and len(axes) == 2:
        return all(isinstance(a, int) for a in axes)
    return False

Prevention

When it happens

Trigger: Calling batch_dot(x, y, axes=[[1, 2], [1, 2]]) or any axes spec where either element is itself a list/tuple; porting einsum-style multi-axis contractions from NumPy or tf.tensordot to batch_dot.

Common situations: Migrating tf.tensordot or np.einsum code that contracts multiple axes at once; passing axes from a config that used nested lists; older Keras examples that used list-of-lists axes syntax.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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