huggingface/candle · error
dim {dim} is odd
Error message
dim {dim} is odd What it means
The rope() helper in flux/model.rs computes rotary position embeddings by splitting the dimension into even/odd halves, so it requires dim to be even. If an odd head dimension reaches it, bail! returns Err("dim {dim} is odd") instead of producing a broken frequency table.
Source
Thrown at candle-transformers/src/models/flux/model.rs:82
fn scaled_dot_product_attention(q: &Tensor, k: &Tensor, v: &Tensor) -> Result<Tensor> {
let dim = q.dim(D::Minus1)?;
let scale_factor = 1.0 / (dim as f64).sqrt();
let mut batch_dims = q.dims().to_vec();
batch_dims.pop();
batch_dims.pop();
let q = q.flatten_to(batch_dims.len() - 1)?;
let k = k.flatten_to(batch_dims.len() - 1)?;
let v = v.flatten_to(batch_dims.len() - 1)?;
let attn_weights = (q.matmul(&k.t()?)? * scale_factor)?;
let attn_scores = candle_nn::ops::softmax_last_dim(&attn_weights)?.matmul(&v)?;
batch_dims.push(attn_scores.dim(D::Minus2)?);
batch_dims.push(attn_scores.dim(D::Minus1)?);
attn_scores.reshape(batch_dims)
}
fn rope(pos: &Tensor, dim: usize, theta: usize) -> Result<Tensor> {
if dim % 2 == 1 {
candle::bail!("dim {dim} is odd")
}
let dev = pos.device();
let theta = theta as f64;
let inv_freq: Vec<_> = (0..dim)
.step_by(2)
.map(|i| 1f32 / theta.powf(i as f64 / dim as f64) as f32)
.collect();
let inv_freq_len = inv_freq.len();
let inv_freq = Tensor::from_vec(inv_freq, (1, 1, inv_freq_len), dev)?;
let inv_freq = inv_freq.to_dtype(pos.dtype())?;
let freqs = pos.unsqueeze(2)?.broadcast_mul(&inv_freq)?;
let cos = freqs.cos()?;
let sin = freqs.sin()?;
let out = Tensor::stack(&[&cos, &sin.neg()?, &sin, &cos], 3)?;
let (b, n, d, _ij) = out.dims4()?;
out.reshape((b, n, d, 2, 2))
}
View on GitHub (pinned to d5fee525bf)
Solutions
- Make hidden_size divisible by num_attention_heads such that head_dim is even (e.g. hidden_size 3072 / heads 12 -> 256).
- Check the Config you pass to FluxModel and revert any custom modifications to standard Flux dimensions.
- If you call rope directly, ensure you pass an even dim (typically the even head_dim from the attention layer).
Example fix
// before
let config = Config { hidden_size: 1537, num_attention_heads: 4, .. };
// head_dim = 1537/4 -> odd downstream
// after
let config = Config { hidden_size: 1536, num_attention_heads: 4, .. };
// head_dim = 384 (even), rope() succeeds Defensive patterns
Strategy: validation
Validate before calling
let head_dim = config.hidden_size / config.num_attention_heads;
if head_dim % 2 != 0 {
return Err(anyhow::anyhow!("head_dim {head_dim} is odd; rope requires even dim"));
} Type guard
fn is_even_dim(dim: usize) -> bool { dim % 2 == 0 } Try / catch
match rope(&pos, head_dim, theta) {
Ok(freqs) => freqs,
Err(e) if e.to_string().ends_with("is odd") => {
anyhow::bail!("fix model config so hidden_size/num_heads is even: {e}")
}
Err(e) => return Err(e.into()),
} Prevention
- Keep hidden_size divisible by num_attention_heads with an even quotient.
- Use upstream Flux default dimensions unless you've verified compatibility.
- Add an assert!(head_dim % 2 == 0) when constructing attention layers.
When it happens
Trigger: Calling rope(pos, dim, theta) with an odd dim — practically, a Fluxmodel built with config.hidden_size not divisible by the number of attention heads, giving an odd per-head head_dim that flows through forward -> rope.
Common situations: Hand-editing Flux model config (hidden_size or num_attention_heads) so hidden_size/num_heads is odd; using a custom/modified Flux variant with an unusual embedding width.
Related errors
- {dim} is odd
- unexpected len from chunk {ys:?}
- unexpected shape for txt {:?}
- unexpected shape for img {:?}
- unexpected len from chunk {ys:?}
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/8df463be3e16f69d.
Report an issue: GitHub.