{"record":{"id":"85a3e9ca4c8f6c1d","repo":"keras-team/keras","slug":"rank-of-condition-should-be-less-than-or-equal-t","errorCode":null,"errorMessage":"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}","messagePattern":"Rank of `condition` should be less than or equal to rank of `then_expression` and `else_expression`\\. ndim\\(condition\\)=(.+?), ndim\\(then_expression\\)=(.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/legacy/backend.py","lineNumber":2149,"sourceCode":"        if not callable(else_expression):\n\n            def else_expression_fn():\n                return else_expression\n\n        else:\n            else_expression_fn = else_expression\n        x = tf.compat.v1.cond(condition, then_expression_fn, else_expression_fn)\n    else:\n        # tf.where needs its condition tensor\n        # to be the same shape as its two\n        # result tensors\n        if callable(then_expression):\n            then_expression = then_expression()\n        if callable(else_expression):\n            else_expression = else_expression()\n        expr_ndim = ndim(then_expression)\n        if cond_ndim > expr_ndim:\n            raise ValueError(\n                \"Rank of `condition` should be less than or\"\n                \" equal to rank of `then_expression` and \"\n                \"`else_expression`. ndim(condition)=\"\n                f\"{cond_ndim}, ndim(then_expression)={expr_ndim}\"\n            )\n        if cond_ndim > 1:\n            ndim_diff = expr_ndim - cond_ndim\n            cond_shape = tf.concat(\n                [tf.shape(condition), [1] * ndim_diff], axis=0\n            )\n            condition = tf.reshape(condition, cond_shape)\n            expr_shape = tf.shape(then_expression)\n            shape_diff = expr_shape - cond_shape\n            tile_shape = tf.where(\n                shape_diff > 0, expr_shape, tf.ones_like(expr_shape)\n            )\n            condition = tf.tile(condition, tile_shape)\n        x = tf.where(condition, then_expression, else_expression)","sourceCodeStart":2131,"sourceCodeEnd":2167,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/legacy/backend.py#L2131-L2167","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nout = switch(cond, a, b)  # cond: (32,10,5), a/b: (32,10)\n# after\ncond2 = tf.reduce_any(cond, axis=-1)  # (32,10)\nout = switch(cond2, a, b)","handlingStrategy":"validation","validationCode":"import tensorflow as tf\nthen_e = then_expression() if callable(then_expression) else then_expression\nassert len(cond.shape) <= len(then_e.shape), (cond.shape, then_e.shape)","typeGuard":null,"tryCatchPattern":"try:\n    out = switch(cond, a, b)\nexcept ValueError as e:\n    if 'Rank of `condition`' in str(e):\n        cond = tf.reduce_any(cond, axis=-1)\n        out = switch(cond, a, b)\n    else:\n        raise","preventionTips":["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"],"tags":["keras","broadcasting","rank-mismatch","legacy","switch"],"backgroundTag":"tensor-rank-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}