huggingface/candle · error

slice-assign requires input with the same rank

Error message

slice-assign requires input with the same rank {} <> {}

What it means

Tensor::slice_assign writes a source tensor into a rectangular region of self defined by ranges. Both tensors must have the same number of dimensions, because each dim of src is matched pairwise with a range and a dim of self. When ranks differ, the method bails reporting self's rank and src's rank.

Solutions

  1. Unsqueeze or reshape src so its rank equals self's rank
  2. Verify both shapes with t.dims().len() == src.dims().len() before the call
  3. Use tensor.narrow/cat to build the result if a full reassignment is simpler

Example fix

// before
t.slice_assign(&(0..2, 1..3), &src)?; // src is rank 1
// after
let src = src.unsqueeze(0)?; // now rank 2
t.slice_assign(&(0..2, 1..3), &src)?;
Defensive patterns

Strategy: validation

Validate before calling

if src.dims().len() != t.dims().len() {
    panic!("rank mismatch: {} vs {}", t.dims().len(), src.dims().len());
}

Try / catch

let src = if src.dims().len() != t.dims().len() { src.unsqueeze(0)? } else { src };
t.slice_assign(ranges, &src)?;

Prevention

When it happens

Trigger: tensor.slice_assign(&[(0..2)?], &src) where src.rank() != self.rank(), e.g. assigning a 1-D vector into a 2-D tensor region.

Common situations: Forgetting to unsqueeze src before slice-assigning into a batched tensor; passing a scalar/1-D row where a rank-N slice was required; shape refactors after adding a batch dimension.

Related errors


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

Appendix: source

Thrown at candle-core/src/tensor.rs:2870

        } else {
            let last = rank - 1;
            let t = self.transpose(dim, last)?;
            let t = t.broadcast_matmul(&triu)?;
            t.transpose(dim, last)
        }
    }

    /// Returns a copy of `self` where the values within `ranges` have been replaced with the
    /// content of `src`.
    pub fn slice_assign<D: std::ops::RangeBounds<usize>>(
        &self,
        ranges: &[D],
        src: &Tensor,
    ) -> Result<Self> {
        let src_dims = src.dims();
        let self_dims = self.dims();
        if self_dims.len() != src_dims.len() {
            bail!(
                "slice-assign requires input with the same rank {} <> {}",
                self_dims.len(),
                src_dims.len()
            )
        }
        if self_dims.len() != ranges.len() {
            bail!(
                "slice-assign requires input with the same rank as there are ranges {} <> {}",
                self_dims.len(),
                ranges.len()
            )
        }
        let mut src = src.clone();
        let mut mask = Self::ones(src.shape(), DType::U8, src.device())?;
        for (i, range) in ranges.iter().enumerate() {
            let start_included = match range.start_bound() {
                std::ops::Bound::Unbounded => 0,
                std::ops::Bound::Included(v) => *v,

View on GitHub (pinned to d5fee525bf)