tracel-ai/burn · error
ndarray gather_nd requires contiguous indices
Error message
ndarray gather_nd requires contiguous indices
What it means
gather_nd flattens `indices` with as_slice() for direct flat indexing; non-contiguous index arrays make as_slice() return None and this expect() panics. Indices must be a densely stored integer tensor.
Source
Thrown at crates/burn-ndarray/src/ops/base.rs:416
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];
for n in 0..num_indices {
let mut base_offset = 0usize;
for j in 0..k {
let idx_val = idx_flat[n * k + j].elem::<i64>() as usize;View on GitHub (pinned to d16f7ba2ed)
Solutions
- Call .contiguous() (or .into_owned()) on the indices tensor before gather
- Construct index tensors contiguously from the start (from_data/from_ints) instead of reshaping views
- If indices come from arithmetic on views, insert a materializing op (e.g. cat of one tensor) to force a copy
Example fix
// before let idx = raw_idx.slice([0..n]).transpose(); let out = data.gather(idx); // after let idx = raw_idx.slice([0..n]).transpose().contiguous(); let out = data.gather(idx);
Defensive patterns
Strategy: validation
Validate before calling
fn contiguous_idx(t: &Tensor<NdArray<Ibd>, D>) -> Tensor<NdArray<Ibd>, D> {
t.clone().int_into_contiguous() // materialize index tensor before gather
}
// let out = data.gather(contiguous_idx(&indices)); Prevention
- Build index tensors contiguously (from_data/from_ints) rather than reshaping views
- Insert .contiguous() after any slice/permute of indices
- Avoid broadcasting/expand to construct gather indices; build the full tensor instead
When it happens
Trigger: Calling Tensor::gather (gather_nd) where the `indices` tensor is a non-contiguous view (slice, permute, broadcast, or result of zero-stride expand), so ArrayD::as_slice() returns None.
Common situations: Building index tensors via broadcasting/expand then gathering; slicing a larger index tensor before gather; ONNX graphs where GatherND indices come from a transposed tensor.
Related errors
- ndarray gather_nd requires contiguous data
- ndarray scatter_nd requires contiguous indices
- ndarray scatter_nd requires contiguous values
- gather_nd: shape mismatch
- float_gather: unsupported dtype {:?}
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/760a3a522c46299f.
Report an issue: GitHub.