{"record":{"id":"2566c5f24f278949","repo":"Hmbown/CodeWhale","slug":"no-pet-segment-was-prepared-native","errorCode":null,"errorMessage":"No pet segment was prepared.","messagePattern":"No pet segment was prepared\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/ios/Resources/pet-native.js","lineNumber":66,"sourceCode":"    }\n    /** Losing a producer invalidates outstanding coverage, never the creature. */\n    disconnectEngine() { this.engine = new pet_engine_js_1.PetEngineTelemetry(); this.world.voices = []; }\n    interact(kind, x, y) { this.world.interact(kind, x, y); }\n    interactions() { return JSON.stringify(this.world.interactions); }\n    accept(packet) { this.world.acceptTelemetry(JSON.parse(packet)); }\n    acceptLiveTail(text) {\n        const packet = this.liveTape.readTail(text);\n        if (!packet)\n            return false;\n        this.world.acceptTelemetry(packet);\n        return true;\n    }\n    resetLiveInput() { this.liveTape.reset(); return this.resumeEngine(); }\n    recording(withCheckpoint = false) { return JSON.stringify(this.world.recording(withCheckpoint)); }\n    needsSegment() { return this.world.needsSegment; }\n    prepareSegment() { this.segment = this.world.prepareSegment(); return JSON.stringify(this.segment.recording); }\n    commitSegment() { if (!this.segment)\n        throw new Error('No pet segment was prepared.'); this.segment.commit(); this.segment = undefined; }\n    checkpoint() { return JSON.stringify(this.world.checkpoint()); }\n    recordingChunk(index, completed = false) { return this.world.recordingChunk(index, completed); }\n    restoreCheckpoint(text) {\n        if (text.length > 512 * 1024)\n            throw new Error('Pet checkpoint exceeds its size limit.');\n        this.restoreRecording(JSON.stringify({ ...this.world.recording(false), checkpoint: JSON.parse(text) }));\n    }\n    restoreRecording(text) {\n        if (text.length > 8 * 1024 * 1024)\n            throw new Error('Native habitat exceeds 8 MiB.');\n        const points = this.world.sim.p.map(p => [p.hx, p.hy]);\n        this.world = pet_world_js_1.PetWorld.fromRecording(points, JSON.parse(text));\n        this.liveTape.reset();\n        this.segment = undefined;\n        this.engineTick = Math.round(this.world.frame.timeMs * 30 / 1000);\n        this.engine = new pet_engine_js_1.PetEngineTelemetry();\n    }\n    /** Resume a live host at the first unrecorded bucket. Keep every accepted","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/ios/Resources/pet-native.js#L48-L84","documentation":"commitSegment() finalizes a recording segment previously created by prepareSegment(). The bridge stores the pending segment in this.segment; if commitSegment() is called without a prior prepareSegment(), or after the segment was already committed (which resets this.segment to undefined), there is nothing to commit and the bridge throws.","triggerScenarios":"Calling commitSegment() when needsSegment()/prepareSegment() was never invoked, or calling commitSegment() twice in a row (the first call sets this.segment = undefined), or after restoreRecording()/restoreCheckpoint() which also clears this.segment.","commonSituations":"Race between the recording UI and a checkpoint restore that wiped the pending segment; double-commit on a completion callback firing twice; forgetting to call prepareSegment() after needsSegment() returned true.","solutions":["Call prepareSegment() and confirm it returned a recording JSON before calling commitSegment().","Guard with needsSegment() before the prepare/commit pair and ensure it runs once per segment.","Check whether a restoreCheckpoint/restoreRecording call reset the bridge state between prepare and commit.","Deduplicate the commit callback so commitSegment() only runs once per segment."],"exampleFix":"// before\nbridge.prepareSegment();\nbridge.commitSegment();\nbridge.commitSegment(); // throws: segment already consumed\n// after\nif (bridge.needsSegment()) {\n  bridge.prepareSegment();\n  bridge.commitSegment(); // exactly once\n}","handlingStrategy":"type-guard","validationCode":"if (bridge.needsSegment()) {\n  bridge.prepareSegment();\n  pendingSegment = true;\n}\n// later, once:\nif (pendingSegment) { bridge.commitSegment(); pendingSegment = false; }","typeGuard":"function canCommit(bridge, pendingSegment) {\n  return pendingSegment === true && typeof bridge.prepareSegment === 'function';\n}","tryCatchPattern":"try {\n  bridge.commitSegment();\n} catch (e) {\n  if (e.message === 'No pet segment was prepared.') {\n    // segment already committed or consumed by a restore; reset local flag\n    pendingSegment = false;\n  } else throw e;\n}","preventionTips":["Track pending-segment state locally and commit exactly once.","Re-prepare after any restoreCheckpoint/restoreRecording call, which clears the pending segment.","Deduplicate completion callbacks that could double-commit."],"tags":["state","lifecycle","recording"],"backgroundTag":"invalid-state-transition","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}