{"record":{"id":"1943b831a8e98ad4","repo":"huggingface/candle","slug":"axis-axis-is-too-large-tensor-rank-rank","errorCode":null,"errorMessage":"axis {axis} is too large, tensor rank {rank}","messagePattern":"axis (.+?) is too large, tensor rank (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"candle-core/src/tensor.rs","lineNumber":2802,"sourceCode":"    /// Unique key for this tensor's storage. Equal keys mean the tensors share the same allocation.\n    #[inline]\n    pub(crate) fn storage_key(&self) -> usize {\n        let lock: &RwLock<Storage> = self.storage.as_ref();\n        std::ptr::from_ref(lock).addr()\n    }\n\n    /// Check if two tensors share the same underlying allocation.\n    #[inline]\n    pub(crate) fn same_storage(&self, rhs: &Self) -> bool {\n        self.storage_key() == rhs.storage_key()\n    }\n\n    /// Normalize a 'relative' axis value: positive values are kept, negative\n    /// values means counting the dimensions from the back.\n    pub fn normalize_axis(&self, axis: i64) -> Result<usize> {\n        let rank = self.rank() as i64;\n        if rank <= axis {\n            bail!(\"axis {axis} is too large, tensor rank {rank}\")\n        } else if 0 <= axis {\n            Ok(axis as usize)\n        } else {\n            let naxis = rank + axis;\n            if naxis < 0 {\n                bail!(\"axis {axis} is too small, tensor rank {rank}\")\n            }\n            Ok(naxis as usize)\n        }\n    }\n\n    /// Returns a lower triangular matrix of ones of size n by n.\n    pub fn tril2(n: usize, dtype: DType, device: &Device) -> Result<Self> {\n        let t = Tensor::arange(0u32, n as u32, device)?;\n        let t1 = t.reshape((1, n))?.broadcast_as((n, n))?;\n        let t2 = t.reshape((n, 1))?.broadcast_as((n, n))?;\n        t1.le(&t2)?.to_dtype(dtype)\n    }","sourceCodeStart":2784,"sourceCodeEnd":2820,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-core/src/tensor.rs#L2784-L2820","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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 }"],"exampleFix":"// before\nlet idx = t.normalize_axis(3)?; // rank 2 tensor\n// after\nlet idx = t.normalize_axis((3 + t.rank() as i64) % t.rank() as i64)?; // or use axis 1","handlingStrategy":"validation","validationCode":"let axis: i64 = 3;\nif axis >= t.rank() as i64 {\n    panic!(\"axis {} >= rank {}\", axis, t.rank());\n}","typeGuard":null,"tryCatchPattern":"let idx = t.normalize_axis(axis)\n    .map_err(|e| { log::warn!(\"axis {} invalid for rank {}\", axis, t.rank()); e })?;","preventionTips":["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"],"tags":["rust","candle","axis","shape"],"backgroundTag":"axis-out-of-range","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}