{"record":{"id":"5f2b613d8c5f2cd6","repo":"tracel-ai/burn","slug":"expand-cannot-expand-dimension-from-to","errorCode":null,"errorMessage":"expand: cannot expand dimension {} from {} to {}","messagePattern":"expand: cannot expand dimension (.+?) from (.+?) to (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-flex/src/ops/expand.rs","lineNumber":121,"sourceCode":"    for i in 0..target_ndims {\n        let target_dim = target_shape[i];\n\n        if i < dim_diff {\n            // New dimension prepended - must be broadcastable from size 1\n            new_strides.push(0);\n        } else {\n            let src_idx = i - dim_diff;\n            let src_dim = src_dims[src_idx];\n            let src_stride = src_strides[src_idx];\n\n            if src_dim == target_dim {\n                // Same size - keep stride\n                new_strides.push(src_stride);\n            } else if src_dim == 1 {\n                // Broadcast dimension - stride becomes 0\n                new_strides.push(0);\n            } else {\n                panic!(\n                    \"expand: cannot expand dimension {} from {} to {}\",\n                    i, src_dim, target_dim\n                );\n            }\n        }\n    }\n\n    let new_layout = Layout::new(target_shape, new_strides, start_offset);\n    FlexTensor::from_arc(tensor.data_arc(), new_layout, dtype)\n}\n\n// Tests kept here probe flex-internal expand behavior: stride metadata\n// (stride 0 on broadcast dims, preservation of negative strides on\n// flipped inputs, preserved start-offset on narrowed inputs) and the\n// flex-only `broadcast_binary` helper. Public-API expand coverage for\n// transpose/flip/narrow variants lives in\n// crates/burn-backend-tests/tests/tensor/{float,int,bool}/ops/expand.rs\n// so it runs on every backend.","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-flex/src/ops/expand.rs#L103-L139","documentation":"The flex backend's expand (broadcast) op can only grow a dimension whose source size is 1, or keep a dimension whose size already equals the target. If a source dimension has size >1 and differs from the requested target size, no valid stride can describe the result, so the backend panics. This is a shape/broadcastability violation caught at layout-construction time.","triggerScenarios":"Calling tensor.expand/expand_to (or any broadcasting binary op that routes through expand) with a target shape where an existing dimension of size N>1 is expected to become M, with M != N. E.g. expanding [4, 1] to [4, 3] is fine, but [4, 2] to [4, 3] panics.","commonSituations":"Manually computed target shapes that don't match the actual input shape (off-by-one or stale constant); mixing tensors whose shapes changed upstream; NumPy-style broadcasting assumptions applied in reverse (expand cannot shrink or resize); feeding a tensor of batch size B into a layer hard-coded for a different batch.","solutions":["Check the source tensor's shape with tensor.shape() and confirm every dimension is either equal to the target or of size 1","Fix the target shape so it only prepends new dimensions or grows size-1 dimensions (proper broadcasting)","If you need arbitrary resizing, use an actual resize op (interpolate/upsample) or slice+concat, not expand","Verify the input tensor wasn't produced by an upstream op with an unexpected shape (log shapes before expand)"],"exampleFix":"// before: src [4, 2], target [4, 3] -> panic\nlet out = x.expand([4, 3]);\n// after: broadcast only size-1 or matching dims\nlet x = x.unsqueeze::<2>(); // e.g. [4, 2, 1]\nlet out = x.expand([4, 2, 3]); // dim of size 1 grows to 3","handlingStrategy":"validation","validationCode":"fn assert_broadcastable(src: &[usize], target: &[usize]) -> Result<(), String> {\n    if target.len() < src.len() {\n        return Err(format!(\"target rank {} < source rank {}\", target.len(), src.len()));\n    }\n    let skip = target.len() - src.len();\n    for (i, (&s, &t)) in src.iter().zip(&target[skip..]).enumerate() {\n        if s != t && s != 1 {\n            return Err(format!(\"dim {} (size {}) cannot expand to {}\", i, s, t));\n        }\n    }\n    Ok(())\n}","typeGuard":"fn can_expand(src_dim: usize, target_dim: usize) -> bool {\n    src_dim == target_dim || src_dim == 1\n}","tryCatchPattern":null,"preventionTips":["Log source and target shapes immediately before any expand/broadcast call","Derive target shapes from input shapes at runtime instead of hard-coding constants","Use unsqueeze to add size-1 dims explicitly rather than expecting expand to resize","Add assert_broadcastable-style checks in helper functions wrapping expand"],"tags":["rust","tensor","broadcasting","shape-mismatch","panic"],"backgroundTag":"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"}