nexu-io/open-design · error · SystemExit

source atlas must be {ATLAS_WIDTH}x{ATLAS_HEIGHT}; got {sour

Error message

source atlas must be {ATLAS_WIDTH}x{ATLAS_HEIGHT}; got {source.width}x{source.height}

What it means

Thrown by compose_from_source_atlas() in compose_atlas.py when a --source-atlas image's pixel dimensions do not equal ATLAS_WIDTH x ATLAS_HEIGHT (1536x1872 for the Codex pet grid) and --resize-source was not passed. Without consent to resize, the script refuses to silently distort a mismatched atlas.

Source

Thrown at skills/hatch-pet/scripts/compose_atlas.py:74

        files.extend(p for p in root.glob(pattern) if p.suffix.lower() in IMAGE_SUFFIXES)
    return sorted(set(files))


def paste_centered(atlas: Image.Image, source: Image.Image, row: int, column: int) -> None:
    frame = source.convert("RGBA")
    if frame.size != (CELL_WIDTH, CELL_HEIGHT):
        frame.thumbnail((CELL_WIDTH, CELL_HEIGHT), Image.Resampling.LANCZOS)
    left = column * CELL_WIDTH + (CELL_WIDTH - frame.width) // 2
    top = row * CELL_HEIGHT + (CELL_HEIGHT - frame.height) // 2
    atlas.alpha_composite(frame, (left, top))


def compose_from_source_atlas(path: Path, resize_source: bool) -> Image.Image:
    with Image.open(path) as opened:
        source = opened.convert("RGBA")
    if source.size != (ATLAS_WIDTH, ATLAS_HEIGHT):
        if not resize_source:
            raise SystemExit(
                f"source atlas must be {ATLAS_WIDTH}x{ATLAS_HEIGHT}; got {source.width}x{source.height}"
            )
        source_ratio = source.width / source.height
        if abs(source_ratio - ATLAS_ASPECT_RATIO) > 0.02:
            raise SystemExit(
                "refusing to resize source atlas because its aspect ratio does not match "
                f"the Codex atlas ratio {ATLAS_ASPECT_RATIO:.3f}; got {source_ratio:.3f}. "
                "Generate exact atlas dimensions or use --frames-root."
            )
        source = source.resize((ATLAS_WIDTH, ATLAS_HEIGHT), Image.Resampling.LANCZOS)

    atlas = Image.new("RGBA", (ATLAS_WIDTH, ATLAS_HEIGHT), (0, 0, 0, 0))
    for _state, row, frame_count in ROW_SPECS:
        for column in range(frame_count):
            left = column * CELL_WIDTH
            top = row * CELL_HEIGHT
            cell = source.crop((left, top, left + CELL_WIDTH, top + CELL_HEIGHT))
            atlas.alpha_composite(cell, (left, top))

View on GitHub (pinned to 5be4028344)

Solutions

  1. Regenerate the source atlas at exactly 1536x1872 (8*192 by 9*208).
  2. Pass --resize-source if (and only if) the source already has the correct aspect ratio so the resize is lossless in shape.
  3. Switch to --frames-root to compose the atlas from individual frame files instead of a precomposed sheet.

Example fix

# before
python compose_atlas.py --source-atlas sheet.png --output out.png  # wrong size
# after
python compose_atlas.py --source-atlas sheet.png --output out.png --resize-source  # only if aspect matches
Defensive patterns

Strategy: validation

Validate before calling

from PIL import Image
ATLAS_W, ATLAS_H = 1536, 1872
def assert_atlas_size(path):
    with Image.open(path) as im:
        if im.size != (ATLAS_W, ATLAS_H):
            raise SystemExit(f"atlas is {im.width}x{im.height}; need {ATLAS_W}x{ATLAS_H} or pass --resize-source")

Prevention

When it happens

Trigger: Run compose_atlas.py --source-atlas <png> without --resize-source where the image is not exactly 1536x1872 (8 columns x 192px by 9 rows x 208px).

Common situations: Using a lower-resolution or differently-cropped source atlas; exporting at the wrong canvas size from an image editor; feeding a single-frame sprite instead of a full atlas.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/dea414d4314604e8. Report an issue: GitHub.