{"record":{"id":"338f33fc0d5fd1bc","repo":"huggingface/candle","slug":"input-has-to-be-contiguous-338f33","errorCode":null,"errorMessage":"input has to be contiguous","messagePattern":"input has to be contiguous","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"candle-core/src/sort.rs","lineNumber":13,"sourceCode":"use crate::{Result, Tensor};\nuse rayon::prelude::*;\n\n#[derive(Debug, Clone, Copy)]\nstruct ArgSort {\n    asc: bool,\n    last_dim: usize,\n}\n\nimpl ArgSort {\n    fn asort<T: crate::WithDType>(&self, vs: &[T], layout: &crate::Layout) -> Result<Vec<u32>> {\n        let vs = match layout.contiguous_offsets() {\n            None => crate::bail!(\"input has to be contiguous\"),\n            Some((o1, o2)) => &vs[o1..o2],\n        };\n        #[allow(clippy::uninit_vec)]\n        // Safety: indexes are set later in the parallelized section.\n        let mut sort_indexes = unsafe {\n            let el_count = layout.shape().elem_count();\n            let mut v = Vec::with_capacity(el_count);\n            v.set_len(el_count);\n            v\n        };\n        if self.asc {\n            sort_indexes\n                .par_chunks_exact_mut(self.last_dim)\n                .zip(vs.par_chunks_exact(self.last_dim))\n                .for_each(|(indexes, vs)| {\n                    indexes\n                        .iter_mut()\n                        .enumerate()","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-core/src/sort.rs#L1-L31","documentation":"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.","triggerScenarios":"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().","commonSituations":"Sorting a transposed matrix on CPU; argsort after narrow/slice operations; chaining ops that return views (candle ops often return lazily-strided tensors).","solutions":["Call .contiguous() on the tensor before arg_sort","Alternatively reshape/copy so the layout becomes contiguous","Check with tensor.layout() or just defensively call contiguous() in helper code before sort-like ops"],"exampleFix":"// before\nlet idx = x.t()?.arg_sort(Ascending)?;\n// after\nlet idx = x.t()?.contiguous()?.arg_sort(Ascending)?;","handlingStrategy":"validation","validationCode":"if x.layout().contiguous_offsets().is_none() {\n    x = x.contiguous()?;\n}\nlet idx = x.arg_sort(Ascending)?;","typeGuard":null,"tryCatchPattern":"let idx = match x.arg_sort(Ascending) {\n    Ok(i) => i,\n    Err(e) if e.to_string().contains(\"contiguous\") => x.contiguous()?.arg_sort(Ascending)?,\n    Err(e) => return Err(e.into()),\n};","preventionTips":["Call .contiguous() after transpose/permute/slice before sort-like ops","Prefer ops that return contiguous tensors on the hot path","Wrap sort helpers so they always materialize contiguity internally"],"tags":["candle","argsort","contiguity","cpu"],"backgroundTag":"tensor-not-contiguous","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}