tracel-ai/burn · error
ndarray gather_nd requires contiguous data
Error message
ndarray gather_nd requires contiguous data
What it means
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.
Source
Thrown at crates/burn-ndarray/src/ops/base.rs:412
) -> SharedArray<E> {
let data_shape: Vec<usize> = data.shape().to_vec();
let idx_shape: Vec<usize> = indices.shape().to_vec();
let m = idx_shape.len();
let k = idx_shape[m - 1];
// Number of index tuples
let num_indices: usize = idx_shape[..m - 1].iter().product();
// Size of each output slice
let slice_size: usize = data_shape[k..].iter().product();
// Output shape: idx_shape[..m-1] ++ data_shape[k..]
let mut out_shape_vec: Vec<usize> = idx_shape[..m - 1].to_vec();
out_shape_vec.extend_from_slice(&data_shape[k..]);
let out_total = num_indices * slice_size;
let data_flat = data
.as_slice()
.expect("ndarray gather_nd requires contiguous data");
let idx_flat = indices
.as_slice()
.expect("ndarray gather_nd requires contiguous indices");
let strides: Vec<usize> = {
let mut s = vec![0usize; k];
if k > 0 {
s[k - 1] = slice_size;
for i in (0..k - 1).rev() {
s[i] = s[i + 1] * data_shape[i + 1];
}
}
s
};
let mut output_vec: Vec<E> = vec![0.elem::<E>(); out_total];
View on GitHub (pinned to d16f7ba2ed)
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()
Example fix
// before let table = embeddings.slice([0..vocab]).permute([1, 0]); let picked = table.gather(indices); // after let table = embeddings.slice([0..vocab]).permute([1, 0]).contiguous(); let picked = table.gather(indices);
Defensive patterns
Strategy: validation
Validate before calling
fn contiguous_check<E: burn_ndarray::FloatElement>(t: &Tensor<NdArray<E>, D>) -> Tensor<NdArray<E>, D> {
t.clone().float_into_contiguous() // materialize before gather
}
// let out = contiguous_check(&data).gather(indices); Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- ndarray gather_nd requires contiguous indices
- ndarray scatter_nd requires contiguous values
- gather_nd: shape mismatch
- float_gather: unsupported dtype {:?}
- ndarray scatter_nd requires contiguous data
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/d6aebc62bb8c3cc3.
Report an issue: GitHub.