huggingface/candle · error

axis {axis} is too small, tensor rank {rank}

Error message

axis {axis} is too small, tensor rank {rank}

What it means

Tensor::normalize_axis supports negative axes by counting from the back: naxis = rank + axis. If the negative axis is so negative that naxis < 0 (i.e. axis < -rank), it does not address any dimension, so the method bails reporting the axis and rank.

Source

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

    /// Check if two tensors share the same underlying allocation.
    #[inline]
    pub(crate) fn same_storage(&self, rhs: &Self) -> bool {
        self.storage_key() == rhs.storage_key()
    }

    /// Normalize a 'relative' axis value: positive values are kept, negative
    /// values means counting the dimensions from the back.
    pub fn normalize_axis(&self, axis: i64) -> Result<usize> {
        let rank = self.rank() as i64;
        if rank <= axis {
            bail!("axis {axis} is too large, tensor rank {rank}")
        } else if 0 <= axis {
            Ok(axis as usize)
        } else {
            let naxis = rank + axis;
            if naxis < 0 {
                bail!("axis {axis} is too small, tensor rank {rank}")
            }
            Ok(naxis as usize)
        }
    }

    /// Returns a lower triangular matrix of ones of size n by n.
    pub fn tril2(n: usize, dtype: DType, device: &Device) -> Result<Self> {
        let t = Tensor::arange(0u32, n as u32, device)?;
        let t1 = t.reshape((1, n))?.broadcast_as((n, n))?;
        let t2 = t.reshape((n, 1))?.broadcast_as((n, n))?;
        t1.le(&t2)?.to_dtype(dtype)
    }

    /// Returns an upper triangular matrix of ones of size n by n.
    pub fn triu2(n: usize, dtype: DType, device: &Device) -> Result<Self> {
        let t = Tensor::arange(0u32, n as u32, device)?;
        let t1 = t.reshape((1, n))?.broadcast_as((n, n))?;
        let t2 = t.reshape((n, 1))?.broadcast_as((n, n))?;

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Ensure axis is in the valid range -rank..=rank-1 before calling
  2. Clamp or recompute the axis from the actual tensor rank at runtime
  3. Add a debug_assert/log of t.rank() near the call site

Example fix

// before
let idx = t.normalize_axis(-2)?; // rank 1 tensor -> naxis = -1
// after
let axis = -2i64;
assert!(axis >= -(t.rank() as i64));
let idx = t.normalize_axis(axis)?;
Defensive patterns

Strategy: validation

Validate before calling

let axis: i64 = -2;
if axis < -(t.rank() as i64) {
    panic!("axis {} too negative for rank {}", axis, t.rank());
}

Try / catch

let idx = t.normalize_axis(axis)
    .with_context(|| format!("axis {} invalid for rank {}", axis, t.rank()))?;

Prevention

When it happens

Trigger: Calling tensor.normalize_axis(-4) on a rank-3 tensor, or passing an axis < -rank to APIs using normalize_axis.

Common situations: Hardcoded negative axis like -1 applied after the tensor was squeezed to fewer dims; config-driven axis values not validated against the actual rank; batched models where an extra dim changes what -2 refers to.

Related errors


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