{"record":{"id":"6f8686a30f309214","repo":"stablyai/orca","slug":"spritesheet-is-too-large-sheetstat-size-102","errorCode":null,"errorMessage":"Spritesheet is too large (${(sheetStat.size / (1024 * 1024)).toFixed(1)} MB).","messagePattern":"Spritesheet is too large \\((.+?) MB\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/pet.ts","lineNumber":322,"sourceCode":"    if (await isSymlink(sheetSrc)) {\n      throw new Error('spritesheet must not be a symlink.')\n    }\n    const sheetClass = classifyFile(sheetSrc)\n    if (!sheetClass || sheetClass.ext === '.svg') {\n      // SVG can't be used as a sprite sheet (no pixel grid).\n      throw new Error('Spritesheet must be a PNG, APNG, JPG, GIF, or WebP.')\n    }\n    let sheetStat: Awaited<ReturnType<typeof stat>>\n    try {\n      sheetStat = await stat(sheetSrc)\n    } catch {\n      throw new Error('Spritesheet file not found.')\n    }\n    if (!sheetStat.isFile()) {\n      throw new Error('Spritesheet path is not a file.')\n    }\n    if (sheetStat.size > MAX_BYTES) {\n      throw new Error(\n        `Spritesheet is too large (${(sheetStat.size / (1024 * 1024)).toFixed(1)} MB).`\n      )\n    }\n\n    let sprite: NonNullable<CustomPet['sprite']> | undefined\n    if (manifest.frame) {\n      // Why: only decode when a frame layout needs validating — nativeImage can fail on some WebP variants in headless contexts.\n      const sheetBuf = await readFile(sheetSrc)\n      // Why: defend against TOCTOU — file may have grown between stat and read.\n      if (sheetBuf.byteLength > MAX_BYTES) {\n        throw new Error('Spritesheet exceeded the size limit.')\n      }\n      const dims = await readSheetDimensions(sheetBuf)\n      if (!dims) {\n        throw new Error('Could not decode the spritesheet image.')\n      }\n      const { width: fw, height: fh } = manifest.frame\n      if (dims.width % fw !== 0 || dims.height % fh !== 0) {","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/pet.ts#L304-L340","documentation":"Thrown at pet.ts:321-324 when sheetStat.size exceeds MAX_BYTES (64*1024*1024 = 64 MB). This bounds the spritesheet so a user cannot point the import at a multi-gigabyte file and OOM the renderer when it builds a Blob URL. The message includes the actual size in MB for clarity.","triggerScenarios":"The spritesheet file is larger than 64 MB at the time stat() runs. Any image format that passes the classifyFile gate can trigger it if the file is oversized.","commonSituations":"An uncompressed PNG from a high-resolution source; an APNG with many frames; a GIF with a large palette; a bundle author who did not downscale the source art.","solutions":["Downscale or recompress the image so it is under 64 MB (e.g. reduce frame count, lower resolution to the actual frame dimensions).","For animated sheets, reduce the number of frames or use APNG/WebP compression.","Confirm the file is a real image and not a mislabeled large binary."],"exampleFix":"# before — 200 MB uncompressed PNG\n# after — re-export at frame resolution\nconvert huge.png -resize 512x512 sheet.png","handlingStrategy":"validation","validationCode":"import { stat } from 'node:fs/promises'\nconst MAX_BYTES = 64 * 1024 * 1024\nasync function assertSheetUnderLimit(p: string) {\n  const st = await stat(p)\n  if (st.size > MAX_BYTES) throw new Error(`spritesheet ${(st.size/1048576).toFixed(1)} MB exceeds 64 MB`)\n}","typeGuard":null,"tryCatchPattern":"try { await importPetBundle(p) }\ncatch (e) { if (e instanceof Error && e.message.startsWith('Spritesheet is too large')) { /* shrink the image */ } else throw e }","preventionTips":["Downscale sprite art to the actual frame resolution before exporting.","Prefer compressed formats (WebP/APNG) for large animated sheets."],"tags":["pet-bundle","size-limit","resource-bounds"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}