nexu-io/open-design · error · SystemExit

expected PNG or WebP, got {image.format}

Error message

expected PNG or WebP, got {image.format}

What it means

Raised by validate_spritesheet when the spritesheet's detected format is neither PNG nor WEBP. The packager converts PNG to lossless WEBP, or copies WEBP verbatim; any other format is rejected because the conversion path does not trust it.

Source

Thrown at skills/hatch-pet/scripts/package_custom_pet.py:36

def default_codex_home() -> Path:
    return Path(os.environ.get("CODEX_HOME") or "~/.codex").expanduser().resolve()


def slugify(value: str) -> str:
    value = value.strip().lower()
    value = re.sub(r"[^a-z0-9]+", "-", value)
    value = re.sub(r"-{2,}", "-", value)
    return value.strip("-")


def validate_spritesheet(path: Path) -> str:
    with Image.open(path) as image:
        if image.size != ATLAS_SIZE:
            raise SystemExit(
                f"expected {ATLAS_SIZE[0]}x{ATLAS_SIZE[1]}, got {image.width}x{image.height}"
            )
        if image.format not in {"PNG", "WEBP"}:
            raise SystemExit(f"expected PNG or WebP, got {image.format}")
        return str(image.format)


def write_webp_spritesheet(source: Path, target: Path, source_format: str) -> None:
    if source_format == "WEBP":
        shutil.copy2(source, target)
        return
    with Image.open(source) as image:
        target.parent.mkdir(parents=True, exist_ok=True)
        image.convert("RGBA").save(
            target,
            format="WEBP",
            lossless=True,
            quality=100,
            method=6,
        )

View on GitHub (pinned to 5be4028344)

Solutions

  1. Re-export/save the spritesheet as PNG (lossless) or WEBP.
  2. Convert in place: python -c "from PIL import Image; Image.open('sheet.jpg').save('sheet.png')".
  3. Re-run package_custom_pet.py --spritesheet sheet.png.
  4. Confirm format: python -c "from PIL import Image; print(Image.open('sheet.png').format)" prints PNG or WEBP.

Example fix

// before
python package_custom_pet.py --spritesheet sheet.jpg ...
# SystemExit: expected PNG or WebP, got JPEG

// after
python -c "from PIL import Image; Image.open('sheet.jpg').save('sheet.png')"
python package_custom_pet.py --spritesheet sheet.png ...
Defensive patterns

Strategy: validation

Validate before calling

from PIL import Image

def check_format(path):
    with Image.open(path) as im:
        if im.format not in {"PNG", "WEBP"}:
            raise SystemExit(f"expected PNG or WEBP, got {im.format}")

Type guard

def is_png_or_webp(path) -> bool:
    with Image.open(path) as im:
        return im.format in {"PNG", "WEBP"}

Prevention

When it happens

Trigger: Passing a JPEG, GIF, BMP, TIFF, or AVIF spritesheet. PIL reports image.format as e.g. "JPEG", which is not in {"PNG", "WEBP"}.

Common situations: Exported the sheet as JPEG (lossy, chroma artifacts); downloaded a GIF/WEBP variant that PIL identifies differently; saved from a tool that defaults to JPEG.

Related errors


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