{"record":{"id":"b36f9605f5d4d670","repo":"invoke-ai/InvokeAI","slug":"latent-spatial-dims-must-be-even-got-h-x-w","errorCode":null,"errorMessage":"Latent spatial dims must be even, got {h}x{w}","messagePattern":"Latent spatial dims must be even, got (.+?)x(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/ernie_image/sampling_utils.py","lineNumber":24,"sourceCode":"\nfrom typing import List\n\nimport torch\n\n# Latent channels of the ERNIE-Image VAE (AutoencoderKLFlux2). The transformer's\n# `in_channels` is this value times 4 (after a 2x2 patchify).\nLATENT_CHANNELS: int = 32\n\n# Total downscale factor between the image and the latent grid. Matches\n# `2 ** len(vae.config.block_out_channels)` for AutoencoderKLFlux2.\nVAE_SCALE_FACTOR: int = 16\n\n\ndef patchify_latents(latents: torch.Tensor) -> torch.Tensor:\n    \"\"\"2x2 patchify: [B, 32, H, W] -> [B, 128, H/2, W/2].\"\"\"\n    b, c, h, w = latents.shape\n    if h % 2 or w % 2:\n        raise ValueError(f\"Latent spatial dims must be even, got {h}x{w}\")\n    latents = latents.view(b, c, h // 2, 2, w // 2, 2)\n    latents = latents.permute(0, 1, 3, 5, 2, 4)\n    return latents.reshape(b, c * 4, h // 2, w // 2)\n\n\ndef unpatchify_latents(latents: torch.Tensor) -> torch.Tensor:\n    \"\"\"Reverse 2x2 patchify: [B, 128, H/2, W/2] -> [B, 32, H, W].\"\"\"\n    b, c, h, w = latents.shape\n    latents = latents.reshape(b, c // 4, 2, 2, h, w)\n    latents = latents.permute(0, 1, 4, 2, 5, 3)\n    return latents.reshape(b, c // 4, h * 2, w * 2)\n\n\ndef pad_text(\n    text_hiddens: List[torch.Tensor],\n    device: torch.device,\n    dtype: torch.dtype,\n    text_in_dim: int,","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/ernie_image/sampling_utils.py#L6-L42","documentation":"patchify_latents performs a 2x2 patchify ([B,32,H,W] -> [B,128,H/2,W/2]) by reshaping spatial dims, which is only valid when both H and W are even. Odd dimensions would lose pixels or break the view/permute, so the function raises ValueError with the offending dims.","triggerScenarios":"Calling patchify_latents on a latent tensor whose height or width is odd — e.g. latent size 33x41 produced by encoding an image whose dimensions don't round to a multiple of the VAE downscale factor.","commonSituations":"User-supplied images with odd pixel dimensions after VAE encoding (dim/8 rounding); custom resize logic producing non-multiple-of-16 latents; img2img pipelines not padding inputs.","solutions":["Resize/pad the input image so latents are even (image dimensions multiple of 2*VAE_scale, e.g. multiples of 16 px).","Center-crop the latents down to even H and W before patchifying.","Round width/height choices in the UI/graph to the model's supported multiples."],"exampleFix":"// before\nlatents = vae.encode(image_501x333)  # -> 63x42? no: 62x41 odd\npatchify_latents(latents)  # raises\n// after\nimage = image.resize((512, 512))  # multiples of 16\nlatents = vae.encode(image)\npatchify_latents(latents)","handlingStrategy":"validation","validationCode":"b, c, h, w = latents.shape\nassert h % 2 == 0 and w % 2 == 0, f\"pad/crop latents before patchify: {h}x{w}\"","typeGuard":"def is_patchifiable(latents: torch.Tensor) -> bool:\n    return latents.dim() == 4 and latents.shape[-2] % 2 == 0 and latents.shape[-1] % 2 == 0","tryCatchPattern":"try:\n    patched = patchify_latents(latents)\nexcept ValueError as e:\n    if \"must be even\" in str(e):\n        b, c, h, w = latents.shape\n        latents = latents[:, :, : h - h % 2, : w - w % 2]\n        patched = patchify_latents(latents)\n    else:\n        raise","preventionTips":["Constrain image sizes to multiples of 16 (VAE downscale x patch size).","Pad or center-crop inputs before VAE encoding.","Validate latent H/W parity in the graph before the diffusion node."],"tags":["pytorch","shape-mismatch","vae","validation"],"backgroundTag":"shape-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}