huggingface/candle · error

input has to be contiguous

Error message

input has to be contiguous

What it means

The CPU argsort kernel (ArgSort::asort) requires the input layout to be contiguous so it can slice vs[o1..o2] directly. If layout.contiguous_offsets() returns None — the tensor is non-contiguous (strided view, transposed slice, etc.) — it bails with this message.

Source

Thrown at candle-core/src/sort.rs:13

use crate::{Result, Tensor};
use rayon::prelude::*;

#[derive(Debug, Clone, Copy)]
struct ArgSort {
    asc: bool,
    last_dim: usize,
}

impl ArgSort {
    fn asort<T: crate::WithDType>(&self, vs: &[T], layout: &crate::Layout) -> Result<Vec<u32>> {
        let vs = match layout.contiguous_offsets() {
            None => crate::bail!("input has to be contiguous"),
            Some((o1, o2)) => &vs[o1..o2],
        };
        #[allow(clippy::uninit_vec)]
        // Safety: indexes are set later in the parallelized section.
        let mut sort_indexes = unsafe {
            let el_count = layout.shape().elem_count();
            let mut v = Vec::with_capacity(el_count);
            v.set_len(el_count);
            v
        };
        if self.asc {
            sort_indexes
                .par_chunks_exact_mut(self.last_dim)
                .zip(vs.par_chunks_exact(self.last_dim))
                .for_each(|(indexes, vs)| {
                    indexes
                        .iter_mut()
                        .enumerate()

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Call .contiguous() on the tensor before arg_sort
  2. Alternatively reshape/copy so the layout becomes contiguous
  3. Check with tensor.layout() or just defensively call contiguous() in helper code before sort-like ops

Example fix

// before
let idx = x.t()?.arg_sort(Ascending)?;
// after
let idx = x.t()?.contiguous()?.arg_sort(Ascending)?;
Defensive patterns

Strategy: validation

Validate before calling

if x.layout().contiguous_offsets().is_none() {
    x = x.contiguous()?;
}
let idx = x.arg_sort(Ascending)?;

Try / catch

let idx = match x.arg_sort(Ascending) {
    Ok(i) => i,
    Err(e) if e.to_string().contains("contiguous") => x.contiguous()?.arg_sort(Ascending)?,
    Err(e) => return Err(e.into()),
};

Prevention

When it happens

Trigger: Calling tensor.arg_sort(...) on a non-contiguous tensor, e.g. one produced by .t() (transpose), slicing, strided indexing, or permute without a subsequent .contiguous().

Common situations: Sorting a transposed matrix on CPU; argsort after narrow/slice operations; chaining ops that return views (candle ops often return lazily-strided tensors).

Related errors


AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02). Data as JSON: /api/errors/338f33fc0d5fd1bc. Report an issue: GitHub.