{"record":{"id":"e8b6b28aeda22968","repo":"stablyai/orca","slug":"animation-name-has-anim-frames-frames-but","errorCode":null,"errorMessage":"Animation \"${name}\" has ${anim.frames} frames but sheet only has ${columns} columns.","messagePattern":"Animation \"(.+?)\" has (.+?) frames but sheet only has (.+?) columns\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/pet.ts","lineNumber":353,"sourceCode":"      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) {\n        throw new Error(\n          `Spritesheet ${dims.width}×${dims.height} is not a clean multiple of frame ${fw}×${fh}.`\n        )\n      }\n      const columns = dims.width / fw\n      const rows = dims.height / fh\n      if (manifest.animations) {\n        for (const [name, anim] of Object.entries(manifest.animations)) {\n          if (anim.row >= rows) {\n            throw new Error(`Animation \"${name}\" references row ${anim.row} but sheet has ${rows}.`)\n          }\n          if (anim.frames > columns) {\n            throw new Error(\n              `Animation \"${name}\" has ${anim.frames} frames but sheet only has ${columns} columns.`\n            )\n          }\n          if (anim.frameDurationsMs && anim.frameDurationsMs.length !== anim.frames) {\n            throw new Error(\n              `Animation \"${name}\" declares ${anim.frameDurationsMs.length} frame durations but ${anim.frames} frames.`\n            )\n          }\n        }\n        if (manifest.defaultAnimation && !manifest.animations[manifest.defaultAnimation]) {\n          throw new Error(`defaultAnimation \"${manifest.defaultAnimation}\" not in animations.`)\n        }\n      }\n      sprite = {\n        frameWidth: fw,\n        frameHeight: fh,\n        columns,\n        rows,","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/pet.ts#L335-L371","documentation":"Thrown at pet.ts:352-355 when an animation declares more frames (anim.frames) than the sheet has columns (sheetWidth / frameWidth). Columns are zero-based count, so a sheet with 8 columns supports up to 8 frames per animation row.","triggerScenarios":"An animation sets frames: 10 but the sheet only has 8 columns. Runs inside the manifest.animations loop at line 348.","commonSituations":"Author miscounted columns; frame.width was set too large reducing columns; animation 'frames' confused with total frames across the row.","solutions":["Reduce anim.frames to be less than or equal to columns (the message states columns).","Or widen the sheet / reduce frame.width to increase columns.","Re-export the bundle after fixing pet.json."],"exampleFix":"// before — 8-column sheet, animation claims 10 frames\n{ \"animations\": { \"run\": { \"row\": 1, \"frames\": 10 } } }\n// after\n{ \"animations\": { \"run\": { \"row\": 1, \"frames\": 8 } } }","handlingStrategy":"validation","validationCode":"function validateAnimationsFrames(animations: Record<string, {frames:number}>, columns: number) {\n  for (const [name, a] of Object.entries(animations)) {\n    if (a.frames > columns) throw new Error(`animation ${name} frames ${a.frames} exceed columns ${columns}`)\n  }\n}","typeGuard":null,"tryCatchPattern":"try { await importPetBundle(p) }\ncatch (e) { if (e instanceof Error && /frames but sheet only has/.test(e.message)) { /* reduce frames or widen sheet */ } else throw e }","preventionTips":["Count the columns in your sheet and never declare more frames per animation than columns.","Re-validate animations whenever the sheet width or frame width changes."],"tags":["pet-bundle","animation","sprite-sheet","validation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}