stablyai/orca · error · Error
Spritesheet path is not a file.
Error message
Spritesheet path is not a file.
What it means
Thrown at pet.ts:318-319 when stat(sheetSrc) succeeds but sheetStat.isFile() is false — the path resolves to a directory, device, FIFO, socket, or block special file rather than a regular file. This is distinct from 1246 (stat threw) and catches the case where the path exists but is the wrong kind of inode.
Source
Thrown at src/main/ipc/pet.ts:319
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) {
// 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.')View on GitHub (pinned to 1136503c6a)
Solutions
- Point spritesheetPath at a single regular image file, not a directory.
- If frames are separate images, combine them into a single sprite sheet first.
Example fix
// before
{ "spritesheetPath": "frames/" } // a directory
// after — combine frames into one sheet, then reference it
{ "spritesheetPath": "spritesheet.png" } Defensive patterns
Strategy: validation
Validate before calling
import { stat } from 'node:fs/promises'
async function assertSheetIsRegularFile(p: string) {
const st = await stat(p)
if (!st.isFile()) throw new Error(`${p} is not a regular file`)
} Try / catch
try { await importPetBundle(p) }
catch (e) { if (e instanceof Error && e.message === 'Spritesheet path is not a file.') { /* point at a file, not a dir */ } else throw e } Prevention
- Point spritesheetPath at a single image file, never a directory of frames.
- Combine per-frame images into one sprite sheet before bundling.
When it happens
Trigger: spritesheetPath names a subdirectory or a special file inside the bundle; the bundle was assembled so that 'spritesheet.png' is actually a folder containing frames.
Common situations: Bundle author pointed spritesheetPath at a directory of frames instead of a single sheet; a leftover FIFO/socket from a botched extraction.
Related errors
- No Claude credentials found in ${resolvedDir}. Run `claude l
- --serve-project-root must be a directory: ${options.projectR
- Selected file is not a markdown document.
- Upload source changed while being inspected: ${sourcePath}
- Cannot download to a directory
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/0b06f5e879a46d78.
Report an issue: GitHub.