{"record":{"id":"697e600b3c05964c","repo":"huggingface/candle","slug":"input1-has-to-be-contiguous","errorCode":null,"errorMessage":"input1 has to be contiguous","messagePattern":"input1 has to be contiguous","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"candle-transformers/src/models/segment_anything/image_encoder.rs","lineNumber":64,"sourceCode":"    fn name(&self) -> &'static str {\n        \"add3\"\n    }\n\n    fn cpu_fwd(\n        &self,\n        s1: &candle::CpuStorage,\n        l1: &candle::Layout,\n        s2: &candle::CpuStorage,\n        l2: &candle::Layout,\n        s3: &candle::CpuStorage,\n        l3: &candle::Layout,\n    ) -> Result<(candle::CpuStorage, candle::Shape)> {\n        use rayon::prelude::*;\n\n        let Add3(b, q_h, q_w, k_h, k_w) = *self;\n        let s1 = s1.as_slice::<f32>()?;\n        let s1 = match l1.contiguous_offsets() {\n            None => candle::bail!(\"input1 has to be contiguous\"),\n            Some((o1, o2)) => &s1[o1..o2],\n        };\n        let s2 = s2.as_slice::<f32>()?;\n        let s2 = match l2.contiguous_offsets() {\n            None => candle::bail!(\"input2 has to be contiguous\"),\n            Some((o1, o2)) => &s2[o1..o2],\n        };\n        let s3 = s3.as_slice::<f32>()?;\n        let s3 = match l3.contiguous_offsets() {\n            None => candle::bail!(\"input3 has to be contiguous\"),\n            Some((o1, o2)) => &s3[o1..o2],\n        };\n        let mut dst = vec![0f32; b * q_h * q_w * k_h * k_w];\n        dst.par_chunks_exact_mut(k_h * k_w)\n            .enumerate()\n            .for_each(|(b_idx, dst)| {\n                let s1_idx = b_idx * k_h * k_w;\n                let s2_idx = b_idx * k_h;","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-transformers/src/models/segment_anything/image_encoder.rs#L46-L82","documentation":"The SAM image encoder's custom Add3 (add-by-broadcast) op implements a fast CPU path that indexes raw f32 data via `contiguous_offsets()`. When the first input layout has no contiguous offset range (tensor is strided/non-contiguous, e.g. after transpose or slicing), slicing raw data would be wrong, so it bails with 'input1 has to be contiguous'.","triggerScenarios":"Calling the image encoder's forward with the first of the three summed tensors (the image embedding/Q side) in a non-contiguous layout — typically the direct result of `transpose`, `permute`, `narrow`, or `broadcast` without an intervening `.contiguous()` call, on the CPU backend.","commonSituations":"Hitting this after modifying SAM internals to skip a `.contiguous()` call for performance; passing transposed key tensors into the attention add; combining tensors produced by broadcasting that were never materialized.","solutions":["Call `.contiguous()?` on the offending input tensor before the op that feeds Add3.","Use `.transpose(0,1)?.contiguous()?` (as done elsewhere in this file) to materialize strided views.","If you changed model code to remove a contiguous() for speed, restore it or add a strided-kernel path.","Ensure you're on the CPU path the op supports; GPU dispatch uses a different kernel."],"exampleFix":"// before\nlet x = q.transpose(0, 1);\nlet out = add3(x, k, v)?;\n// after\nlet out = add3(q.transpose(0, 1)?.contiguous()?, k, v)?;","handlingStrategy":"validation","validationCode":"fn ensure_contiguous(t: &Tensor) -> candle::Result<Tensor> {\n    if t.layout().contiguous_offsets().is_none() { t.contiguous() } else { Ok(t.clone()) }\n}\nlet q = ensure_contiguous(&input1)?;","typeGuard":"fn is_contiguous(t: &Tensor) -> bool {\n    t.layout().contiguous_offsets().is_some()\n}","tryCatchPattern":"match add3_forward(x1, x2, x3) {\n    Ok(t) => t,\n    Err(e) if e.to_string().contains(\"has to be contiguous\") => {\n        add3_forward(x1.contiguous()?, x2.contiguous()?, x3.contiguous()?)\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Call .contiguous() after any transpose/permute/narrow before custom CPU ops.","Remember PyTorch-style lazy views don't carry over: candle custom kernels read raw pointers.","Prefer standard candle ops over fused custom ops unless profiling demands it.","Test model paths with strided inputs in CI."],"tags":["cpu","contiguity","custom-op","candle"],"backgroundTag":"tensor-not-contiguous","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}