{"record":{"id":"6e96ccfb47fbb376","repo":"tracel-ai/burn","slug":"failed-to-broadcast-lhs","errorCode":null,"errorMessage":"Failed to broadcast lhs","messagePattern":"Failed to broadcast lhs","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-ndarray/src/ops/base.rs","lineNumber":837,"sourceCode":"        } else if lhs_dim == 1 {\n            broadcast_shape[ndims - 1 - i] = rhs_dim;\n        } else if rhs_dim == 1 {\n            broadcast_shape[ndims - 1 - i] = lhs_dim;\n        } else {\n            panic!(\n                \"Incompatible shapes for broadcasting: {:?} and {:?}\",\n                lhs_shape, rhs_shape\n            );\n        }\n    }\n\n    // Create IxDyn from broadcast shape\n    let broadcast_dim = ndarray::IxDyn(&broadcast_shape);\n\n    // Broadcast both arrays\n    let lhs_broadcast = lhs\n        .broadcast(broadcast_dim.clone())\n        .expect(\"Failed to broadcast lhs\");\n    let rhs_broadcast = rhs\n        .broadcast(broadcast_dim)\n        .expect(\"Failed to broadcast rhs\");\n\n    (lhs_broadcast, rhs_broadcast)\n}\n\n/// The mean of zero elements, which is `0 / 0`.\n///\n/// `NaN` for a float, matching numpy and torch. Integers have no such value, so an integer mean of\n/// nothing is rejected rather than silently reported as some other number.\npub(crate) fn empty_mean<E: NdArrayElement>() -> E {\n    assert!(\n        E::dtype().is_float(),\n        \"Cannot compute mean of empty tensor for the integer type {:?}\",\n        E::dtype()\n    );\n    0.elem::<E>() / 0.elem::<E>()","sourceCodeStart":819,"sourceCodeEnd":855,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-ndarray/src/ops/base.rs#L819-L855","documentation":"broadcast_for_binary_ops aligns two tensors for elementwise comparison/remainder ops by broadcasting the left-hand array to the merged shape. If lhs cannot be broadcast to that shape (its trailing dims neither match nor are 1), ndarray returns Err and this expect() panics.","triggerScenarios":"Calling remainder, equal, greater, greater_equal, lower_equal or lower on tensors whose shapes are not broadcastable - e.g. [2, 3] vs [4, 3], or trailing dims that don't match and neither side is 1.","commonSituations":"Comparing tensors from different pipeline branches whose batch/spatial dims diverged; comparing [N] with [M]; a reshape dropped/changed a dim upstream so comparison operands no longer align.","solutions":["Print/check both tensor dims and make them broadcastable: equal dims, or one side's dim == 1 (right-aligned)","Insert reshape/expand or squeeze/unsqueeze so ranks align before the comparison","Fix upstream ops (cat, slice, reshape) that produced divergent shapes"],"exampleFix":"// before\nlet a: Tensor<NdArray, 2> = ...; // [2, 3]\nlet b: Tensor<NdArray, 2> = ...; // [4, 3]\nlet eq = a.equal(b); // panic\n// after\nlet a2 = a.reshape([1, 2, 3]);\nlet eq = a2.equal(b.reshape([1, 4, 3]).transpose()); // make shapes align/broadcastable","handlingStrategy":"validation","validationCode":"fn broadcastable(a: &[usize], b: &[usize]) -> bool {\n    let n = a.len().max(b.len());\n    (0..n).all(|i| {\n        let da = a.get(a.len().checked_sub(1 + i).unwrap_or(usize::MAX)).copied();\n        let db = b.get(b.len().checked_sub(1 + i).unwrap_or(usize::MAX)).copied();\n        match (da, db) { (Some(x), Some(y)) => x == y || x == 1 || y == 1, _ => true }\n    })\n}\n// assert!(broadcastable(&lhs.dims(), &rhs.dims()));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check both operand dims before equal/greater/lower/remainder ops","Use unsqueeze/reshape to align ranks when comparing tensors from different branches","Watch for batch/spatial dims diverging after slice/cat in dual-branch models","Log shapes at comparison sites during development"],"tags":["rust","ndarray","panic","broadcast","elementwise","shape"],"backgroundTag":"tensor-broadcast-shape-mismatch","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}