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
- Reshape or reduce the condition so its rank <= branch rank (e.g. tf.reduce_any over the extra axis)
- Expand the branch tensors' rank with tf.expand_dims to meet or exceed the condition's rank
- 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
- Unit-test custom losses with tensors of the exact production shapes
- Reduce masks explicitly (reduce_any/reshape) instead of relying on broadcast in backend.switch
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
- Inputs have incompatible shapes. Received shapes {shape1} an
- A `Concatenate` layer requires inputs with matching shapes e
- Cannot do batch_dot on inputs with rank < 2. Received inputs
- Unexpected bias dimensions {len(bias_shape)}. Expected it to
- Expected `padding` to be a tuple of 3 tuples of 2 integers.
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/85a3e9ca4c8f6c1d.
Report an issue: GitHub.