{"record":{"id":"471d130c3b36aa30","repo":"Hmbown/CodeWhale","slug":"unsupported-pet-expression-version","errorCode":null,"errorMessage":"Unsupported pet expression version.","messagePattern":"Unsupported pet expression version\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/pet_watch/pet-native.js","lineNumber":251,"sourceCode":"            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();\n        }\n        return world;\n    }","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/pet_watch/pet-native.js#L233-L269","documentation":"fromRecording resolves the expression version from r.expressionVersion (defaulting to 1 for legacy recordings) and only supports versions 1 and 2. A recording produced with a newer expression/simulation format cannot be interpreted by this binary, so the library refuses it rather than rendering a wrong pet.","triggerScenarios":"Calling `PetWorld.fromRecording(points, r)` where r.expressionVersion is a number other than 1 or 2 (e.g. 3 from a newer app version, or a corrupted/garbage value like a string).","commonSituations":"Opening a recording exported by a newer release of the app in an older binary; a version field corrupted during transfer; hand-editing a recording file and mistyping the version.","solutions":["Upgrade the application/binary to a version that supports the recording's expressionVersion.","Re-export the recording from the newer version in a supported format.","Fix the expressionVersion field if it was accidentally edited or corrupted (must be 1 or 2).","Discard the recording if no compatible producer is available."],"exampleFix":"// before\n// recording has expressionVersion: 3, loaded by binary supporting 1-2\nconst world = PetWorld.fromRecording(points, r); // throws\n// after\n// upgrade the app, or strip/convert:\nr.expressionVersion = 2; // only if you know the semantics did not change\nconst world = PetWorld.fromRecording(points, r);","handlingStrategy":"validation","validationCode":"if (r.expressionVersion !== undefined && ![1, 2].includes(r.expressionVersion))\n  throw new Error(`Recording needs app supporting expressionVersion ${r.expressionVersion}`);","typeGuard":null,"tryCatchPattern":"try {\n  world = PetWorld.fromRecording(points, r);\n} catch (err) {\n  if (err.message === 'Unsupported pet expression version.')\n    notifyUser('Upgrade the app to open this recording.');\n  else throw err;\n}","preventionTips":["Check expressionVersion against the app's supported range before loading.","Gate recording files with a format/version manifest written at export time.","Pin recordings to the app version that produced them when archiving.","Never hand-edit version fields in recording files."],"tags":["versioning","compatibility","deserialization"],"backgroundTag":"unsupported-operation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}