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
- Resize the image so height % patch_h == 0 before forwarding
- Center-crop the image to the nearest multiple of patch_h
- Verify the model's patch_size config matches your preprocessing (e.g. 16 vs 14)
- 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
- Resize/center-crop images to a multiple of the patch size in preprocessing
- Match patch_size config to the checkpoint you load
- Validate input dims (dims4) before model forward
- Use fixed canonical input sizes (e.g. 224x224)
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
- image width {w} is not a multiple of patch width {patch_w}
- only {} / {} blocks found
- bool_masked_pos set without mask_token
- {} is a dummy type and cannot be constructed
- {} is a dummy type and cannot be converted
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/ceac98a1aa9c84c9.
Report an issue: GitHub.