huggingface/candle · error
axis {axis} is too large, tensor rank {rank}
Error message
axis {axis} is too large, tensor rank {rank} What it means
Tensor::normalize_axis converts a possibly-negative axis into a concrete dimension index. If the given axis (already assumed non-negative when this branch fires, or too large after other checks) is >= the tensor's rank, there is no matching dimension, so it bails with the axis value and rank. In this codepath it fires when 0 <= axis and rank <= axis.
Source
Thrown at candle-core/src/tensor.rs:2802
/// Unique key for this tensor's storage. Equal keys mean the tensors share the same allocation.
#[inline]
pub(crate) fn storage_key(&self) -> usize {
let lock: &RwLock<Storage> = self.storage.as_ref();
std::ptr::from_ref(lock).addr()
}
/// 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)
}View on GitHub (pinned to d5fee525bf)
Solutions
- Verify the tensor's rank and use axis < rank (or axis in [-rank, -1] for negative indexing)
- Print/inspect the tensor shape before the call and correct the axis constant
- Guard the call site: if rank <= axis { adjust or error }
Example fix
// before let idx = t.normalize_axis(3)?; // rank 2 tensor // after let idx = t.normalize_axis((3 + t.rank() as i64) % t.rank() as i64)?; // or use axis 1
Defensive patterns
Strategy: validation
Validate before calling
let axis: i64 = 3;
if axis >= t.rank() as i64 {
panic!("axis {} >= rank {}", axis, t.rank());
} Try / catch
let idx = t.normalize_axis(axis)
.map_err(|e| { log::warn!("axis {} invalid for rank {}", axis, t.rank()); e })?; Prevention
- Derive axes from the tensor's rank at runtime, not constants
- Assert rank assumptions near model-shape-defining code
- When porting from PyTorch, recheck dim counts including batch dims
When it happens
Trigger: Calling tensor.normalize_axis(3) on a rank-2 tensor, or passing axis >= rank to APIs that route through normalize_axis (e.g. ops taking axis: i64).
Common situations: Porting PyTorch code where an axis constant assumed a different number of dims; off-by-one from forgetting batch dims were squeezed; framework code passing axis=0 to a 0-dim (scalar) tensor.
Related errors
- axis {axis} is too small, tensor rank {rank}
- unsqueeze: maximum size for tensor at dimension {dim} is {ma
- attribute {} of type TENSOR has a negative dimension, which
- {} is a dummy type and cannot be constructed
- {} is a dummy type and cannot be converted
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/1943b831a8e98ad4.
Report an issue: GitHub.