huggingface/candle · error

image height {h} is not a multiple of patch height {patch_h}

Error message

image height {h} is not a multiple of patch height {patch_h}

What it means

In the BeiT vision model, PatchEmbed::forward splits the input image into fixed-size patches via a convolution. This error is thrown when the input image height is not an exact multiple of the patch height, since leftover pixels cannot form complete patches. It is a hard shape constraint of the patch embedding layer.

Source

Thrown at candle-transformers/src/models/beit.rs:269

    fn new(vb: VarBuilder, patch_size: usize, in_chans: usize, embed_dim: usize) -> Result<Self> {
        let config = candle_nn::Conv2dConfig {
            stride: patch_size,
            ..Default::default()
        };
        let proj = candle_nn::conv2d(in_chans, embed_dim, patch_size, config, vb.pp("proj"))?;
        Ok(Self {
            proj,
            patch_size: (patch_size, patch_size),
        })
    }
}

impl Module for PatchEmbed {
    fn forward(&self, xs: &Tensor) -> Result<Tensor> {
        let (_b, _c, h, w) = xs.dims4()?;
        let (patch_h, patch_w) = self.patch_size;
        if (h % patch_h) != 0 {
            candle::bail!("image height {h} is not a multiple of patch height {patch_h}")
        }
        if (w % patch_w) != 0 {
            candle::bail!("image width {w} is not a multiple of patch width {patch_w}")
        }
        let xs = self.proj.forward(xs)?;
        let (b, c, h, w) = xs.dims4()?;
        // flatten embeddings.
        xs.reshape((b, c, h * w))?.transpose(1, 2)
    }
}

#[derive(Debug)]
pub struct BeitVisionTransformer {
    patch_embed: PatchEmbed,
    cls_token: Tensor,
    blocks: Vec<Block>,
    norm: LayerNorm,
    head: Linear,

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Resize the image so height % patch_h == 0 before forwarding
  2. Center-crop the image to the nearest multiple of patch_h
  3. Verify the model's patch_size config matches your preprocessing (e.g. 16 vs 14)
  4. Check for unwanted padding that changed the height

Example fix

// before
let xs = Tensor::from_shape((1, 3, 225, 224), ...)?; // 225 % 16 != 0
// after
let xs = Tensor::from_shape((1, 3, 224, 224), ...)?; // 224 % 16 == 0
Defensive patterns

Strategy: validation

Validate before calling

let (patch_h, _) = model.patch_size;
let (_, _, h, _) = xs.dims4()?;
assert!(h % patch_h == 0, "height {} not multiple of {}", h, patch_h);

Type guard

fn is_valid_image_size(dims: (usize, usize), patch: (usize, usize)) -> bool {
    dims.0 % patch.0 == 0 && dims.1 % patch.1 == 0
}

Try / catch

match patch_embed.forward(&xs) {
    Ok(v) => v,
    Err(e) if e.to_string().contains("not a multiple") => {
        let xs = resize_to_multiple(&xs, model.patch_size)?;
        patch_embed.forward(&xs)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Forwarding an image tensor whose H dimension is not divisible by the model's patch_size.0, e.g. a 224x225 image with patch height 16.

Common situations: Resizing/preprocessing pipelines producing odd image sizes, mixing models with different patch sizes (14 vs 16), or cropped images not resized to a multiple of the patch size.

Related errors


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