huggingface/candle · error
input1 has to be contiguous
Error message
input1 has to be contiguous
What it means
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'.
Source
Thrown at candle-transformers/src/models/segment_anything/image_encoder.rs:64
fn name(&self) -> &'static str {
"add3"
}
fn cpu_fwd(
&self,
s1: &candle::CpuStorage,
l1: &candle::Layout,
s2: &candle::CpuStorage,
l2: &candle::Layout,
s3: &candle::CpuStorage,
l3: &candle::Layout,
) -> Result<(candle::CpuStorage, candle::Shape)> {
use rayon::prelude::*;
let Add3(b, q_h, q_w, k_h, k_w) = *self;
let s1 = s1.as_slice::<f32>()?;
let s1 = match l1.contiguous_offsets() {
None => candle::bail!("input1 has to be contiguous"),
Some((o1, o2)) => &s1[o1..o2],
};
let s2 = s2.as_slice::<f32>()?;
let s2 = match l2.contiguous_offsets() {
None => candle::bail!("input2 has to be contiguous"),
Some((o1, o2)) => &s2[o1..o2],
};
let s3 = s3.as_slice::<f32>()?;
let s3 = match l3.contiguous_offsets() {
None => candle::bail!("input3 has to be contiguous"),
Some((o1, o2)) => &s3[o1..o2],
};
let mut dst = vec![0f32; b * q_h * q_w * k_h * k_w];
dst.par_chunks_exact_mut(k_h * k_w)
.enumerate()
.for_each(|(b_idx, dst)| {
let s1_idx = b_idx * k_h * k_w;
let s2_idx = b_idx * k_h;View on GitHub (pinned to d5fee525bf)
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.
Example fix
// before let x = q.transpose(0, 1); let out = add3(x, k, v)?; // after let out = add3(q.transpose(0, 1)?.contiguous()?, k, v)?;
Defensive patterns
Strategy: validation
Validate before calling
fn ensure_contiguous(t: &Tensor) -> candle::Result<Tensor> {
if t.layout().contiguous_offsets().is_none() { t.contiguous() } else { Ok(t.clone()) }
}
let q = ensure_contiguous(&input1)?; Type guard
fn is_contiguous(t: &Tensor) -> bool {
t.layout().contiguous_offsets().is_some()
} Try / catch
match add3_forward(x1, x2, x3) {
Ok(t) => t,
Err(e) if e.to_string().contains("has to be contiguous") => {
add3_forward(x1.contiguous()?, x2.contiguous()?, x3.contiguous()?)
}
Err(e) => return Err(e.into()),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- input2 has to be contiguous
- input3 has to be contiguous
- input has to be contiguous
- alpha has to be contiguous
- input has to be contiguous
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/697e600b3c05964c.
Report an issue: GitHub.