invoke-ai/InvokeAI · error · ValueError

image size (({image_width}, {image_height})) must be divisib

Error message

image size (({image_width}, {image_height})) must be divisible by {LATENT_SCALE_FACTOR}

What it means

calc_tiles_even_split requires the image dimensions to be divisible by LATENT_SCALE_FACTOR (8) so tiles align to the latent grid. Non-divisible width or height raises this ValueError before any tile math runs.

Source

Thrown at invokeai/backend/tiles/tiles.py:121

def calc_tiles_even_split(
    image_height: int, image_width: int, num_tiles_x: int, num_tiles_y: int, overlap: int = 0
) -> list[Tile]:
    """Calculate the tile coordinates for a given image shape with the number of tiles requested.

    Args:
        image_height (int): The image height in px.
        image_width (int): The image width in px.
        num_x_tiles (int): The number of tile to split the image into on the X-axis.
        num_y_tiles (int): The number of tile to split the image into on the Y-axis.
        overlap (int, optional): The overlap between adjacent tiles in pixels. Defaults to 0.

    Returns:
        list[Tile]: A list of tiles that cover the image shape. Ordered from left-to-right, top-to-bottom.
    """
    # Ensure the image is divisible by LATENT_SCALE_FACTOR
    if image_width % LATENT_SCALE_FACTOR != 0 or image_height % LATENT_SCALE_FACTOR != 0:
        raise ValueError(f"image size (({image_width}, {image_height})) must be divisible by {LATENT_SCALE_FACTOR}")

    # Calculate the tile size based on the number of tiles and overlap, and ensure it's divisible by 8 (rounding down)
    if num_tiles_x > 1:
        # ensure the overlap is not more than the maximum overlap if we only have 1 tile then we dont care about overlap
        assert overlap <= image_width - (LATENT_SCALE_FACTOR * (num_tiles_x - 1))
        tile_size_x = LATENT_SCALE_FACTOR * math.floor(
            ((image_width + overlap * (num_tiles_x - 1)) // num_tiles_x) / LATENT_SCALE_FACTOR
        )
        assert overlap < tile_size_x
    else:
        tile_size_x = image_width

    if num_tiles_y > 1:
        # ensure the overlap is not more than the maximum overlap if we only have 1 tile then we dont care about overlap
        assert overlap <= image_height - (LATENT_SCALE_FACTOR * (num_tiles_y - 1))
        tile_size_y = LATENT_SCALE_FACTOR * math.floor(
            ((image_height + overlap * (num_tiles_y - 1)) // num_tiles_y) / LATENT_SCALE_FACTOR
        )

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Round/pad the image dimensions to the nearest multiple of 8 before tiling
  2. Resize or center-crop the image to an 8-divisible size
  3. Catch the ValueError and rescale the image before invoking

Example fix

// before
tiles = calc_tiles_even_split(image_width=1000, image_height=640, num_tiles=4, overlap=64)
// after
image_width, image_height = (w // 8) * 8 for w in (1000, 640)  # -> 1000→1000? no: use round-down
image_width = 1000 - 1000 % 8  # 1000 is divisible by 8; for 642 -> 640
tiles = calc_tiles_even_split(image_width=image_width, image_height=image_height, num_tiles=4, overlap=64)
Defensive patterns

Strategy: validation

Validate before calling

LATENT_SCALE_FACTOR = 8
if image_width % LATENT_SCALE_FACTOR or image_height % LATENT_SCALE_FACTOR:
    image_width -= image_width % LATENT_SCALE_FACTOR
    image_height -= image_height % LATENT_SCALE_FACTOR
tiles = calc_tiles_even_split(image_width, image_height, num_tiles, overlap)

Type guard

def is_latent_aligned(w: int, h: int, factor: int = 8) -> bool:
    return w % factor == 0 and h % factor == 0

Try / catch

try:
    tiles = calc_tiles_even_split(w, h, num_tiles, overlap)
except ValueError as e:
    if "must be divisible" in str(e):
        w, h = w - w % 8, h - h % 8
        tiles = calc_tiles_even_split(w, h, num_tiles, overlap)
    else:
        raise

Prevention

When it happens

Trigger: Calling calc_tiles_even_split(image_width, image_height, num_tiles, ...) where image_width % 8 != 0 or image_height % 8 != 0, e.g. a 1000x640 or arbitrary user-resized image.

Common situations: User-supplied arbitrary resolutions in the tiled-diffusion invoke path, image resize pipelines producing odd sizes, or tests passing non-aligned dimensions.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/1525ab9222b35a35. Report an issue: GitHub.