{"record":{"id":"f3b8aa2a8bc2e01a","repo":"Hmbown/CodeWhale","slug":"invalid-pet-recording","errorCode":null,"errorMessage":"Invalid pet recording.","messagePattern":"Invalid pet recording\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/pet_watch/pet-native.js","lineNumber":248,"sourceCode":"            random: this.random.state(), behaviour: this.behaviour, until: this.until,\n            targetX: this.targetX, targetY: this.targetY, x: this.x, y: this.y, flip: this.flip, lit: this.lit,\n            lastActivity: this.lastActivity, addressedAt: Number.isFinite(this.addressedAt) ? this.addressedAt : null,\n            waitSince: this.waitSince, food: this.food, members: [...this.members.values()], lastStill: this.lastStill,\n            frame: this.frame, voices: this.voices });\n    }\n    recording(withCheckpoint = true, completed = false) {\n        const tapeEnd = completed ? this.bucketIndex + 1 : this.tapeLog.length;\n        const inputEnd = completed ? this.interactionIndex : this.interactionLog.length;\n        const history = this.historyDigest(tapeEnd, inputEnd);\n        return { petReplayVersion: this.segmented ? 2 : 1, expressionVersion: this.sim.expressionVersion,\n            tape: this.tapeLog.slice(0, tapeEnd), interactions: this.interactionLog.slice(0, inputEnd).map(e => ({ ...e })),\n            ...(this.origin ? { start: { ...structuredClone(this.origin), hasTelemetry: this.hasTelemetry, history } } : {}),\n            ...(withCheckpoint ? { checkpoint: { ...this.checkpoint(), history } } : {}) };\n    }\n    static fromRecording(points, value) {\n        const r = value;\n        if (!r || ![1, 2].includes(r.petReplayVersion) || !Array.isArray(r.tape) || !Array.isArray(r.interactions))\n            throw new Error('Invalid pet recording.');\n        const version = r.expressionVersion === undefined ? 1 : r.expressionVersion;\n        if (![1, 2].includes(version))\n            throw new Error('Unsupported pet expression version.');\n        if (r.checkpoint !== undefined && !r.checkpoint || r.start !== undefined && !r.start)\n            throw new Error('Invalid pet checkpoint.');\n        for (const c of [r.start, r.checkpoint])\n            if (c && (c.sim?.expressionVersion ?? 1) !== version)\n                throw new Error('Pet expression version does not match its checkpoint.');\n        if (r.petReplayVersion === 1 && (r.start || r.checkpoint && r.checkpoint.petCheckpointVersion !== 1))\n            throw new Error('Invalid legacy pet recording.');\n        if (r.petReplayVersion === 2 && (!r.start || r.start.petCheckpointVersion !== 2 || r.start.historyStart !== r.start.tick))\n            throw new Error('The recording segment is missing its starting checkpoint.');\n        const first = r.start && PetWorld.restore(points, r.tape, r.interactions, r.start);\n        const world = r.checkpoint ? PetWorld.restore(points, r.tape, r.interactions, r.checkpoint) : first ?? new PetWorld(points, r.tape, r.interactions, version);\n        if (first) {\n            if (!world.segmented || world.tick < first.tick || r.checkpoint && r.checkpoint.historyStart !== first.tick)\n                throw new Error('Pet segment checkpoints do not agree.');\n            world.origin = first.checkpoint();","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/pet_watch/pet-native.js#L230-L266","documentation":"PetWorld.fromRecording rehydrates a world from a serialized recording object. It first requires a truthy object with petReplayVersion of 1 or 2 and array-valued tape and interactions fields. If the value is null, not an object, has an unknown petReplayVersion, or lacks tape/interactions arrays, the recording cannot be restored and this error is thrown.","triggerScenarios":"Calling `PetWorld.fromRecording(points, value)` where value is null/undefined, value.petReplayVersion is missing or not 1 or 2, value.tape is not an array, or value.interactions is not an array.","commonSituations":"Loading a pet recording file that was truncated or corrupted, feeding JSON parsed from a non-pet file, passing a legacy recording with a petReplayVersion newer than the running binary supports, passing the wrong object (e.g. a checkpoint instead of the recording envelope).","solutions":["Check the recording object before calling: it must be truthy, have petReplayVersion 1 or 2, and array tape and interactions.","Re-export the recording with recordingChunk() from a live world if the file predates the current schema.","Verify the file was fully written (all chunks consumed) before parsing/restoring.","Confirm you are passing the recording envelope, not a checkpoint or chunk fragment."],"exampleFix":"// before\nconst world = PetWorld.fromRecording(points, JSON.parse(raw));\n// after\nconst r = JSON.parse(raw);\nif (!r || ![1, 2].includes(r.petReplayVersion) || !Array.isArray(r.tape) || !Array.isArray(r.interactions))\n  throw new Error('Corrupt pet recording file');\nconst world = PetWorld.fromRecording(points, r);","handlingStrategy":"type-guard","validationCode":"function isPetRecordingEnvelope(r) {\n  return !!r && typeof r === 'object' &&\n    [1, 2].includes(r.petReplayVersion) &&\n    Array.isArray(r.tape) && Array.isArray(r.interactions);\n}","typeGuard":"const isRecording = (v) =>\n  typeof v === 'object' && v !== null &&\n  (v.petReplayVersion === 1 || v.petReplayVersion === 2) &&\n  Array.isArray(v.tape) && Array.isArray(v.interactions);","tryCatchPattern":"let world;\ntry {\n  world = PetWorld.fromRecording(points, parsed);\n} catch (err) {\n  if (err.message === 'Invalid pet recording.')\n    throw new Error(`Recording file corrupt or unsupported: ${path}`);\n  throw err;\n}","preventionTips":["Validate the parsed JSON envelope before restoring.","Ensure export writes all recordingChunk() pieces and verifies completeness before saving.","Only feed fromRecording the full envelope, never a chunk fragment or checkpoint.","Store petReplayVersion alongside the file and check it before parse."],"tags":["deserialization","validation","replay"],"backgroundTag":"schema-validation-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}