keras-team/keras · error · ValueError

Rank of `condition` should be less than or equal to rank of

Error message

Rank of `condition` should be less than or equal to rank of `then_expression` and `else_expression`. ndim(condition)={cond_ndim}, ndim(then_expression)={expr_ndim}

What it means

The legacy `switch` backend function broadcasts a boolean condition against both branches, which requires ndim(condition) <= ndim(then/else branch). If the condition tensor has more axes than the value tensors (e.g. a 3D condition with 2D branches), Keras raises this ValueError rather than attempting an undefined broadcast, mirroring numpy's semantics for np.where.

Source

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

        if not callable(else_expression):

            def else_expression_fn():
                return else_expression

        else:
            else_expression_fn = else_expression
        x = tf.compat.v1.cond(condition, then_expression_fn, else_expression_fn)
    else:
        # tf.where needs its condition tensor
        # to be the same shape as its two
        # result tensors
        if callable(then_expression):
            then_expression = then_expression()
        if callable(else_expression):
            else_expression = else_expression()
        expr_ndim = ndim(then_expression)
        if cond_ndim > expr_ndim:
            raise ValueError(
                "Rank of `condition` should be less than or"
                " equal to rank of `then_expression` and "
                "`else_expression`. ndim(condition)="
                f"{cond_ndim}, ndim(then_expression)={expr_ndim}"
            )
        if cond_ndim > 1:
            ndim_diff = expr_ndim - cond_ndim
            cond_shape = tf.concat(
                [tf.shape(condition), [1] * ndim_diff], axis=0
            )
            condition = tf.reshape(condition, cond_shape)
            expr_shape = tf.shape(then_expression)
            shape_diff = expr_shape - cond_shape
            tile_shape = tf.where(
                shape_diff > 0, expr_shape, tf.ones_like(expr_shape)
            )
            condition = tf.tile(condition, tile_shape)
        x = tf.where(condition, then_expression, else_expression)

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Reshape or reduce the condition so its rank <= branch rank (e.g. tf.reduce_any over the extra axis)
  2. Expand the branch tensors' rank with tf.expand_dims to meet or exceed the condition's rank
  3. Log ndim of all three tensors before calling switch when debugging dynamic shapes

Example fix

# before
out = switch(cond, a, b)  # cond: (32,10,5), a/b: (32,10)
# after
cond2 = tf.reduce_any(cond, axis=-1)  # (32,10)
out = switch(cond2, a, b)
Defensive patterns

Strategy: validation

Validate before calling

import tensorflow as tf
then_e = then_expression() if callable(then_expression) else then_expression
assert len(cond.shape) <= len(then_e.shape), (cond.shape, then_e.shape)

Try / catch

try:
    out = switch(cond, a, b)
except ValueError as e:
    if 'Rank of `condition`' in str(e):
        cond = tf.reduce_any(cond, axis=-1)
        out = switch(cond, a, b)
    else:
        raise

Prevention

When it happens

Trigger: Calling keras._legacy.backend.switch(condition, then_expr, else_expr) where condition.ndim > then_expression.ndim, e.g. condition shape (32,10,5) with branches of shape (32,10); also when branch callables return lower-rank tensors than the condition.

Common situations: Custom losses or regularizers building per-element masks of higher rank than the activation tensors; migrating numpy code to backend ops where masks keep extra dimensions; passing a stacked list where a scalar/1D condition was intended.

Related errors


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