stablyai/orca · error · Error
Could not decode the spritesheet image.
Error message
Could not decode the spritesheet image.
What it means
Thrown at pet.ts:335-337 when readSheetDimensions(sheetBuf) returns null/undefined, meaning the image bytes could not be decoded or the decoder could not extract width/height. This runs only when manifest.frame is set (the decode path at line 328). The comment at line 329 notes nativeImage can fail on some WebP variants in headless contexts.
Source
Thrown at src/main/ipc/pet.ts:337
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) {
// Why: only decode when a frame layout needs validating — nativeImage can fail on some WebP variants in headless contexts.
const sheetBuf = await readFile(sheetSrc)
// Why: defend against TOCTOU — file may have grown between stat and read.
if (sheetBuf.byteLength > MAX_BYTES) {
throw new Error('Spritesheet exceeded the size limit.')
}
const dims = await readSheetDimensions(sheetBuf)
if (!dims) {
throw new Error('Could not decode the spritesheet image.')
}
const { width: fw, height: fh } = manifest.frame
if (dims.width % fw !== 0 || dims.height % fh !== 0) {
throw new Error(
`Spritesheet ${dims.width}×${dims.height} is not a clean multiple of frame ${fw}×${fh}.`
)
}
const columns = dims.width / fw
const rows = dims.height / fh
if (manifest.animations) {
for (const [name, anim] of Object.entries(manifest.animations)) {
if (anim.row >= rows) {
throw new Error(`Animation "${name}" references row ${anim.row} but sheet has ${rows}.`)
}
if (anim.frames > columns) {
throw new Error(
`Animation "${name}" has ${anim.frames} frames but sheet only has ${columns} columns.`
)View on GitHub (pinned to 1136503c6a)
Solutions
- Re-export the image with a real encoder so the bytes match the extension.
- Open the file in an image viewer to confirm it is valid and not truncated.
- If using WebP, try converting to PNG/APNG which have broader decoder support.
- Verify the file is not zero-length.
Example fix
# before — cat.jpg renamed to cat.png mv cat.jpg cat.png # after — re-encode properly convert cat.jpg cat.png
Defensive patterns
Strategy: validation
Validate before calling
import { readFile } from 'node:fs/promises'
import { nativeImage } from 'electron'
async function assertSheetDecodes(p: string) {
const buf = await readFile(p)
const img = nativeImage.createFromBuffer(buf)
const size = img.getSize()
if (!size.width || !size.height) throw new Error('spritesheet does not decode')
} Try / catch
try { await importPetBundle(p) }
catch (e) { if (e instanceof Error && e.message === 'Could not decode the spritesheet image.') { /* re-encode the image */ } else throw e } Prevention
- Re-export images through a real encoder rather than renaming extensions.
- Open the file in an image viewer before bundling to confirm it is valid.
- Prefer PNG/APNG over exotic WebP variants for maximum decoder compatibility.
When it happens
Trigger: The file passed the extension check (1245) but its bytes are not a valid decodable image of that format: a .png that is actually a JPEG, a truncated/corrupt image, an unsupported WebP variant, or a zero-byte file that somehow passed stat.
Common situations: File renamed without re-encoding (e.g. cat.jpg renamed to cat.png); a partially downloaded/truncated image; an exotic WebP/animated format the decoder rejects; a file with correct extension but wrong magic bytes.
Related errors
- Codex reset attempt journal is unreadable
- Artifact create recovery record exceeds the supported size.
- Artifact share records could not be read safely.
- Invalid pet.json: ${error instanceof Error ? error.message :
- spritesheetPath must be relative to the bundle.
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/a96abc97190c44c3.
Report an issue: GitHub.