{"record":{"id":"8b8441dcf48aefa4","repo":"huggingface/candle","slug":"input2-has-to-be-contiguous","errorCode":null,"errorMessage":"input2 has to be contiguous","messagePattern":"input2 has to be contiguous","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"candle-transformers/src/models/segment_anything/image_encoder.rs","lineNumber":69,"sourceCode":"        &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;\n                let s3_idx = b_idx * k_w;\n                for h_idx in 0..k_h {\n                    let s1_idx = s1_idx + h_idx * k_w;\n                    let s2_idx = s2_idx + h_idx;\n                    let dst_idx = h_idx * k_w;","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-transformers/src/models/segment_anything/image_encoder.rs#L51-L87","documentation":"Same custom Add3 op in the SAM image encoder, but for the second input. The CPU kernel reads raw f32 slices via `contiguous_offsets()` on layout l2; if the second tensor's layout is not a single contiguous range it bails to avoid reading wrong data.","triggerScenarios":"The second argument to the add-by-broadcast op (K-side attention tensor) is non-contiguous — usually the output of `transpose`/`permute`/`narrow` passed straight into the encoder's attention add without `.contiguous()`.","commonSituations":"Arises when refactoring the attention computation to fuse reshapes, or when porting PyTorch code where views are lazily strided but this kernel requires materialized memory.","solutions":["Insert `.contiguous()?` on the second input before the op.","Match the pattern used for k in this file: `k.squeeze(0)?.transpose(0, 1)?.contiguous()?`.","If this fires inside library code you didn't modify, check you're calling the public encoder API rather than the raw custom op.","Update candle — later versions may add strided handling."],"exampleFix":"// before\nlet k = keys.transpose(0, 1);\nlet out = add3(q, k, v)?;\n// after\nlet out = add3(q, keys.transpose(0, 1)?.contiguous()?, 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 k = ensure_contiguous(&input2)?;","typeGuard":"fn is_contiguous(t: &Tensor) -> bool {\n    t.layout().contiguous_offsets().is_some()\n}","tryCatchPattern":"match add3_forward(q, k, v) {\n    Ok(t) => t,\n    Err(e) if e.to_string().contains(\"input2 has to be contiguous\") => {\n        add3_forward(q, k.contiguous()?, v)\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Materialize transposed tensors with .contiguous() before feeding custom ops.","Follow the in-file idiom: tensor.transpose(0,1)?.contiguous()?.","Avoid passing broadcast views directly into Add3-style kernels.","Add assertions on contiguity at model boundaries during development."],"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"}