nexu-io/open-design · error · SystemExit
expected {ATLAS_SIZE[0]}x{ATLAS_SIZE[1]}, got {image.width}x
Error message
expected {ATLAS_SIZE[0]}x{ATLAS_SIZE[1]}, got {image.width}x{image.height} What it means
Raised by validate_spritesheet in package_custom_pet.py when the opened spritesheet's pixel size does not equal ATLAS_SIZE (1536x1872). The Codex pet atlas contract requires exactly 8 columns x 9 rows of 192x208 cells, so any other dimensions are rejected before packaging.
Source
Thrown at skills/hatch-pet/scripts/package_custom_pet.py:32
ATLAS_SIZE = (1536, 1872)
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,View on GitHub (pinned to 5be4028344)
Solutions
- Re-export the spritesheet at exactly 1536x1872 with 8 columns x 9 rows of 192x208 cells.
- If you only have the base sprite, run the full prepare_pet_run.py + generate_pet_images.py pipeline to produce all row strips, then assemble them into the 1536x1872 atlas.
- Verify with: python -c "from PIL import Image; print(Image.open('sheet.png').size)".
- Re-run package_custom_pet.py with the corrected sheet.
Example fix
// before python package_custom_pet.py --spritesheet base.png ... # SystemExit: expected 1536x1872, got 1024x1024 // after - resize is NOT enough; rebuild the full atlas # produce all states, then assemble into a 1536x1872 (8 cols x 9 rows of 192x208) sheet python package_custom_pet.py --spritesheet full_atlas.png ...
Defensive patterns
Strategy: validation
Validate before calling
from PIL import Image
ATLAS_SIZE = (1536, 1872)
def check_size(path):
with Image.open(path) as im:
if im.size != ATLAS_SIZE:
raise SystemExit(f"expected {ATLAS_SIZE[0]}x{ATLAS_SIZE[1]}, got {im.size[0]}x{im.size[1]}") Type guard
def is_atlas_size(path) -> bool:
with Image.open(path) as im:
return im.size == (1536, 1872) Prevention
- Author spritesheets against the documented 8x9 grid of 192x208 cells (1536x1872).
- Run the full prepare_pet_run.py + generate_pet_images.py pipeline; do not package a single base sprite as the atlas.
- Add a pre-commit check that asserts spritesheet dimensions before packaging.
When it happens
Trigger: Passing a spritesheet that was exported at a different resolution, with the wrong row/column count, with non-uniform cell sizing, or a single-frame image.
Common situations: Hand-authored art exported at 1024x1024 or another common model output size; a spritesheet built against an older atlas layout; an image that was upscaled/downscaled; using a generated base sprite (1024x1024 default) directly instead of assembling the full atlas.
Related errors
- expected PNG or WebP, got {image.format}
- invalid JSON in ${filePath}: ${message}
- ${filePath} must contain a JSON object
- ARTIFACT_MANIFEST_INVALID
- ARTIFACT_MANIFEST_REQUIRED
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/db575a172ba41b81.
Report an issue: GitHub.