huggingface/candle · error
dimension mismatch in permute, tensor {:?}, dims: {:?}
Error message
dimension mismatch in permute, tensor {:?}, dims: {:?} What it means
Tensor::permute reorders existing dimensions and therefore requires the supplied dims to be a valid permutation of 0..rank — same length as the rank, with every index 0..rank appearing exactly once. Anything else (repeated indices, out-of-range indices, wrong count) triggers this bail, which includes the tensor's dims and the offending dims for debugging.
Source
Thrown at candle-core/src/tensor.rs:2329
/// Returns a tensor with the same data as the input where the dimensions have been permuted.
/// dims must be a permutation, i.e. include each dimension index exactly once.
///
/// ```rust
/// use candle_core::{Tensor, Device};
/// let tensor = Tensor::arange(0u32, 120u32, &Device::Cpu)?.reshape((2, 3, 4, 5))?;
/// assert_eq!(tensor.dims(), &[2, 3, 4, 5]);
/// let tensor = tensor.permute((2, 3, 1, 0))?;
/// assert_eq!(tensor.dims(), &[4, 5, 3, 2]);
/// # Ok::<(), candle_core::Error>(())
/// ```
pub fn permute<D: Dims>(&self, dims: D) -> Result<Tensor> {
let dims = dims.to_indexes(self.shape(), "permute")?;
// O(n^2) permutation check but these arrays are small.
let is_permutation =
dims.len() == self.rank() && (0..dims.len()).all(|i| dims.contains(&i));
if !is_permutation {
bail!(
"dimension mismatch in permute, tensor {:?}, dims: {:?}",
self.dims(),
dims
)
}
let op = BackpropOp::new1(self, |t| Op::Permute(t, dims.clone()));
let tensor_ = Tensor_ {
id: TensorId::new(),
storage: self.storage.clone(),
layout: self.layout.permute(&dims)?,
op,
is_variable: false,
dtype: self.dtype,
device: self.device.clone(),
};
Ok(Tensor(Arc::new(tensor_)))
}
View on GitHub (pinned to d5fee525bf)
Solutions
- Verify dims is a permutation of 0..t.rank(): same length, no duplicates, all indices < rank.
- For a simple two-dimension swap, use t.transpose(d1, d2) instead of permute.
- Print t.dims() and check your permutation against the actual rank.
- For NHWC<->NCHW on 4-D tensors use the standard permutations: [0,3,1,2] and [0,2,3,1].
Example fix
// before let out = img.permute(&[0, 2, 1])?; // img is rank 4 -> error // after let out = img.permute(&[0, 2, 3, 1])?; // valid permutation of 0..4
Defensive patterns
Strategy: validation
Validate before calling
let dims = [0usize, 2, 3, 1];
let r = t.rank();
let is_perm = dims.len() == r && (0..r).all(|i| dims.contains(&i));
if !is_perm {
return Err(anyhow!("invalid permutation {:?} for rank {}", dims, r));
}
let out = t.permute(dims)?; Try / catch
match t.permute(dims) {
Ok(x) => x,
Err(e) if e.to_string().contains("dimension mismatch in permute") => {
eprintln!("rank={}, attempted dims={:?}", t.rank(), dims);
return Err(e.into());
}
Err(e) => return Err(e.into()),
} Prevention
- Use transpose(d1, d2) for simple two-dim swaps instead of permute.
- Derive permutations from rank instead of hardcoding literals.
- Know the standard permutations: NHWC->NCHW is [0,3,1,2]; NCHW->NHWC is [0,2,3,1].
When it happens
Trigger: Calling t.permute(&[0, 2, 1]) on a tensor whose rank doesn't match the dims length; passing duplicate indices like [0,1,1]; using out-of-range indices like [0,3,2] on a rank-3 tensor; confusing permute (permutation of dims) with transpose (swap of two dims).
Common situations: Porting NumPy/PyTorch code with hardcoded permutations to a differently-shaped tensor; off-by-one dims in NHWC<->NCHW conversions; calling permute instead of transpose for a simple two-dim swap.
Related errors
- quantized embedding hidden size {hidden} is not divisible by
- unexpected rhs shape in dmmv {:?}
- mismatch on matmul dim {self_shape:?} {:?}
- unexpected shape for input {s:?}
- only 2d matrixes are supported {lhs:?} {rhs:?}
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/cc6baf9d49a9bfb2.
Report an issue: GitHub.