{"record":{"id":"4d33fe3ce8939c42","repo":"tracel-ai/burn","slug":"ndarray-scatter-nd-requires-contiguous-data","errorCode":null,"errorMessage":"ndarray scatter_nd requires contiguous data","messagePattern":"ndarray scatter_nd requires contiguous data","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-ndarray/src/ops/base.rs","lineNumber":320,"sourceCode":"    where\n        E: core::ops::Mul<Output = E> + PartialOrd,\n    {\n        use burn_backend::tensor::IndexingUpdateOp;\n\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 = product of batch dims (first M-1 dims of indices)\n        let num_indices: usize = idx_shape[..m - 1].iter().product();\n        // Size of each slice to scatter = product of data.shape[K..]\n        let slice_size: usize = data_shape[k..].iter().product();\n\n        let mut output = data.into_owned();\n        let output_flat = output\n            .as_slice_mut()\n            .expect(\"ndarray scatter_nd requires contiguous data\");\n\n        // Flatten indices to [num_indices, K]\n        let idx_flat = indices\n            .as_slice()\n            .expect(\"ndarray scatter_nd requires contiguous indices\");\n\n        // Flatten values to [num_indices, slice_size]\n        let val_flat = values\n            .as_slice()\n            .expect(\"ndarray scatter_nd requires contiguous values\");\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                }","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-ndarray/src/ops/base.rs#L302-L338","documentation":"The ndarray backend's scatter_nd obtains a mutable contiguous slice of the output tensor via as_slice_mut and panics when the data is not stored contiguously (e.g. it is a strided view). The naive scatter implementation only supports contiguous memory, an internal invariant of this backend path.","triggerScenarios":"Calling scatter_nd with a data tensor that is a non-contiguous view/slice produced by prior strided operations (permutes, slicing) on the ndarray backend.","commonSituations":"Chaining reshape/permute/slice operations before scatter_nd; exporting models (e.g. from ONNX-style graphs) that feed non-contiguous intermediates into scatter; custom backend code reusing views.","solutions":["Make the data tensor contiguous before scattering (clone/copy into a fresh owned ArrayD).","Rearrange upstream ops to avoid strided views reaching scatter_nd.","If this fires on standard high-level API usage, report it as a backend bug — upstream burn ops should never hand non-contiguous data to this kernel."],"exampleFix":"// before\nlet out = tensor.slice(s![.., ..2]).scatter(...);\n// after\nlet contiguous = tensor.to_data().convert::<FloatNdArrayElement>();\nlet owned = NdArrayTensor::new(contiguous.into_ndarray()); // fresh contiguous buffer\nlet out = owned.scatter(indices, values);","handlingStrategy":"validation","validationCode":"// Ensure data owns a fresh contiguous buffer before scatter_nd\nlet data_owned = data.to_data(); // deep copy, always contiguous\nlet data = NdArrayTensor::new(data_owned.into_ndarray());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clone/copy tensors after slicing or permuting before scatter","Build scatter inputs from owned tensors, not views","Test scatter paths with tensors produced by slice ops"],"tags":["rust","ndarray","tensor","backend","panic"],"backgroundTag":"non-contiguous-tensor","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"}