stablyai/orca · error · Error
Spritesheet must be a PNG, APNG, JPG, GIF, or WebP.
Error message
Spritesheet must be a PNG, APNG, JPG, GIF, or WebP.
What it means
Thrown at pet.ts:307-310 when classifyFile(sheetSrc) returns null (the extension is not in IMAGE_FORMATS) or the extension is '.svg'. classifyFile lowercases the extension and looks it up in the PNG/APNG/JPG/JPEG/GIF/WebP/SVG map (pet.ts:18-26), but SVG is explicitly rejected here because a sprite sheet needs a pixel grid that SVG lacks.
Source
Thrown at src/main/ipc/pet.ts:310
// Why: bundles exported on Windows may be imported on macOS/Linux; normalize separators before resolving.
const sheetSrc = resolve(bundleDir, normalizedSpritePath)
const bundleResolved = resolve(bundleDir)
if (sheetSrc === bundleResolved) {
throw new Error('spritesheetPath must point to a file, not the bundle root.')
}
const bundleRoot = bundleResolved + sep
// Why: Windows volumes are case-insensitive; lowercase the prefix compare so case differences can't bypass the escape check.
const cmp = process.platform === 'win32' ? (s: string) => s.toLowerCase() : (s: string) => s
if (!cmp(sheetSrc + sep).startsWith(cmp(bundleRoot))) {
throw new Error('spritesheetPath escapes the bundle.')
}
if (await isSymlink(sheetSrc)) {
throw new Error('spritesheet must not be a symlink.')
}
const sheetClass = classifyFile(sheetSrc)
if (!sheetClass || sheetClass.ext === '.svg') {
// SVG can't be used as a sprite sheet (no pixel grid).
throw new Error('Spritesheet must be a PNG, APNG, JPG, GIF, or WebP.')
}
let sheetStat: Awaited<ReturnType<typeof stat>>
try {
sheetStat = await stat(sheetSrc)
} catch {
throw new Error('Spritesheet file not found.')
}
if (!sheetStat.isFile()) {
throw new Error('Spritesheet path is not a file.')
}
if (sheetStat.size > MAX_BYTES) {
throw new Error(
`Spritesheet is too large (${(sheetStat.size / (1024 * 1024)).toFixed(1)} MB).`
)
}
let sprite: NonNullable<CustomPet['sprite']> | undefined
if (manifest.frame) {View on GitHub (pinned to 1136503c6a)
Solutions
- Convert the spritesheet to PNG, APNG, JPG, GIF, or WebP and update spritesheetPath in pet.json.
- If you have an SVG, rasterize it to PNG at the target frame size before bundling.
- Confirm the extension matches the actual file format — a .png-named BMP will decode-fail later even if it passes this gate.
Example fix
# before
{ "spritesheetPath": "cat.svg" }
# after — rasterize and rename
convert cat.svg -resize 32x32 cat.png
{ "spritesheetPath": "cat.png" } Defensive patterns
Strategy: validation
Validate before calling
import { extname } from 'node:path'
const SHEET_EXTS = new Set(['.png', '.apng', '.jpg', '.jpeg', '.gif', '.webp'])
function assertSheetFormat(p: string) {
const ext = extname(p).toLowerCase()
if (!SHEET_EXTS.has(ext)) throw new Error(`unsupported spritesheet extension: ${ext}`)
} Type guard
function isSupportedSheetExt(p: string): boolean {
return SHEET_EXTS.has(extname(p).toLowerCase())
} Try / catch
try { await importPetBundle(p) }
catch (e) { if (e instanceof Error && e.message === 'Spritesheet must be a PNG, APNG, JPG, GIF, or WebP.') { /* convert the image */ } else throw e } Prevention
- Standardize on PNG for static sheets and APNG/WebP for animated ones.
- Make sure the file extension matches the actual encoded format.
When it happens
Trigger: spritesheetPath points to a file whose extension is not .png/.apng/.jpg/.jpeg/.gif/.webp (e.g. .bmp, .tiff, .avif, no extension), or to an .svg file.
Common situations: Bundle author used an unsupported format; file saved as .svg because the design tool defaulted to vector export; uppercase extension is fine (classifyFile lowercases) but a .bmp slipped in.
Related errors
- Invalid pet.json: ${error instanceof Error ? error.message :
- spritesheetPath must be relative to the bundle.
- spritesheetPath must point to a file, not the bundle root.
- spritesheetPath escapes the bundle.
- Spritesheet path is not a file.
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/52161f7d0229b4e9.
Report an issue: GitHub.