huggingface/candle · error

Embedding dimension must be even

Error message

Embedding dimension must be even

What it means

The mmdit timestep_embedding helper builds sinusoidal embeddings by pairing sin/cos frequency channels, which requires dim to be even. An odd embedding dimension cannot be split into two halves, so it bails immediately.

Solutions

  1. Make the timestep embedding dimension even (e.g. round up to the next multiple of 2)
  2. Check that frequency_embedding_size / inner embedding dims in the config are even
  3. Match the checkpoint's expected embedding dimension

Example fix

// before
timestep_embedding(&t, 257, max_period)?; // odd dim bails
// after
timestep_embedding(&t, 256, max_period)?;
Defensive patterns

Strategy: validation

Validate before calling

if dim % 2 != 0 {
    return Err(anyhow::anyhow!("timestep embedding dim must be even, got {dim}"));
}
let emb = timestep_embedding(&t, dim, max_period)?;

Type guard

fn is_even_dim(dim: usize) -> bool { dim % 2 == 0 }

Try / catch

let emb = timestep_embedding(&t, dim, max_period)
    .map_err(|e| if e.to_string().contains("Embedding dimension must be even") {
        anyhow::anyhow!("use an even embedding dim (round up to next even value)")
    } else { e.into() })?;

Prevention

When it happens

Trigger: Calling timestep_embedding (from Timesteps/TimestepEmbedding forward) with an odd dim, usually from a misconfigured frequency_embedding_size or embedding dimension in the mmdit config.

Common situations: Typo in config (odd hidden/frequency embedding size); modifying TimestepEmbedding params and picking an odd dim; deriving dims from arithmetic that yields odd values.

Understand the failure class

Background: Tensor shape mismatch errors ("must have shape", "expected shape ... got ..."): when tensor dimensions disagree with what an op or layer was told to expect — this error's family across 6 libraries.

Related errors


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

Appendix: source

Thrown at candle-transformers/src/models/mmdit/embedding.rs:145

    ) -> Result<Self> {
        let mlp = nn::seq()
            .add(nn::linear(
                frequency_embedding_size,
                hidden_size,
                vb.pp("mlp.0"),
            )?)
            .add(nn::Activation::Silu)
            .add(nn::linear(hidden_size, hidden_size, vb.pp("mlp.2"))?);

        Ok(Self {
            mlp,
            frequency_embedding_size,
        })
    }

    fn timestep_embedding(t: &Tensor, dim: usize, max_period: f64) -> Result<Tensor> {
        if !dim.is_multiple_of(2) {
            bail!("Embedding dimension must be even")
        }

        if t.dtype() != DType::F32 && t.dtype() != DType::F64 {
            bail!("Input tensor must be floating point")
        }

        let half = dim / 2;
        let freqs = Tensor::arange(0f32, half as f32, t.device())?
            .to_dtype(candle::DType::F32)?
            .mul(&Tensor::full(
                (-f64::ln(max_period) / half as f64) as f32,
                half,
                t.device(),
            )?)?
            .exp()?;

        let args = t
            .unsqueeze(1)?

View on GitHub (pinned to d5fee525bf)