{"record":{"id":"d6aebc62bb8c3cc3","repo":"tracel-ai/burn","slug":"ndarray-gather-nd-requires-contiguous-data","errorCode":null,"errorMessage":"ndarray gather_nd requires contiguous data","messagePattern":"ndarray gather_nd requires contiguous data","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-ndarray/src/ops/base.rs","lineNumber":412,"sourceCode":"    ) -> SharedArray<E> {\n        let data_shape: Vec<usize> = data.shape().to_vec();\n        let idx_shape: Vec<usize> = indices.shape().to_vec();\n        let m = idx_shape.len();\n        let k = idx_shape[m - 1];\n\n        // Number of index tuples\n        let num_indices: usize = idx_shape[..m - 1].iter().product();\n        // Size of each output slice\n        let slice_size: usize = data_shape[k..].iter().product();\n\n        // Output shape: idx_shape[..m-1] ++ data_shape[k..]\n        let mut out_shape_vec: Vec<usize> = idx_shape[..m - 1].to_vec();\n        out_shape_vec.extend_from_slice(&data_shape[k..]);\n        let out_total = num_indices * slice_size;\n\n        let data_flat = data\n            .as_slice()\n            .expect(\"ndarray gather_nd requires contiguous data\");\n\n        let idx_flat = indices\n            .as_slice()\n            .expect(\"ndarray gather_nd requires contiguous indices\");\n\n        let strides: Vec<usize> = {\n            let mut s = vec![0usize; k];\n            if k > 0 {\n                s[k - 1] = slice_size;\n                for i in (0..k - 1).rev() {\n                    s[i] = s[i + 1] * data_shape[i + 1];\n                }\n            }\n            s\n        };\n\n        let mut output_vec: Vec<E> = vec![0.elem::<E>(); out_total];\n","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-ndarray/src/ops/base.rs#L394-L430","documentation":"gather_nd collects slices of `data` at positions given by `indices`. The implementation flattens `data` via as_slice() for fast indexing, which returns None for non-contiguous arrays, so the expect() panics. The library assumes gather input is stored contiguously in memory.","triggerScenarios":"Calling Tensor::gather (gather_nd) on the ndarray backend where `data` is a non-contiguous view - result of slicing, transposing/permuting, broadcasting, or other zero-copy view ops - making ArrayD::as_slice() return None.","commonSituations":"Gathering from a transposed activation tensor in a model; gathering rows from a sliced embedding table; passing a broadcasted tensor to gather in ONNX-imported graphs (ONNX GatherND after a broadcast).","solutions":["Call .contiguous() (or .into_owned()) on the data tensor before gather","Materialize views earlier in the pipeline: avoid gather immediately after transpose/slice ops","If the panic originates inside a burn op, ensure ops call try_into_owned_nocopy()/into_owned() before as_slice()"],"exampleFix":"// before\nlet table = embeddings.slice([0..vocab]).permute([1, 0]);\nlet picked = table.gather(indices);\n// after\nlet table = embeddings.slice([0..vocab]).permute([1, 0]).contiguous();\nlet picked = table.gather(indices);","handlingStrategy":"validation","validationCode":"fn contiguous_check<E: burn_ndarray::FloatElement>(t: &Tensor<NdArray<E>, D>) -> Tensor<NdArray<E>, D> {\n    t.clone().float_into_contiguous() // materialize before gather\n}\n// let out = contiguous_check(&data).gather(indices);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never gather directly from a sliced/transposed tensor; insert .contiguous() first","Prefer ops that return owned arrays upstream of gather","For embeddings lookups, keep the table contiguous from initialization","Audit ONNX-imported graphs for Gather/GatherND following Transpose nodes"],"tags":["rust","ndarray","panic","gather","contiguity"],"backgroundTag":"non-contiguous-tensor-view","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"}