{"record":{"id":"5bda3c35af8de8d9","repo":"Hmbown/CodeWhale","slug":"archive-the-legacy-recording-before-accepting-more-telemetry-5bda3c","errorCode":null,"errorMessage":"Archive the legacy recording before accepting more telemetry.","messagePattern":"Archive the legacy recording before accepting more telemetry\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/ios/Resources/pet-native.js","lineNumber":450,"sourceCode":"        this.interactionLog.push({ timeMs: (this.tick + 1) * 1000 / HZ, kind, x, y });\n    }\n    /** Accept a live source packet at the next 400ms boundary. The accepted tape,\n     * including any missing intervals, is the exact replay authority for this host. */\n    acceptTelemetry(input) {\n        (0, pet_telemetry_js_1.validatePetBucket)(input);\n        const sequence = Math.floor(this.tick / 12) + 1;\n        if (this.tapeLog.length >= 216_000)\n            throw new Error('Archive this pet recording before accepting more telemetry.');\n        this.hasTelemetry = true;\n        if (this.segmented) {\n            const at = this.tapeLog.findIndex(b => b.sequence >= sequence);\n            const index = at < 0 ? this.tapeLog.length : at;\n            this.tapeLog.splice(index, at >= 0 && this.tapeLog[at].sequence === sequence ? 1 : 0, { ...structuredClone(input), sequence, simTimeMs: sequence * 400 });\n            this.hashTape(index);\n            return;\n        }\n        if (sequence >= 216_000)\n            throw new Error('Archive the legacy recording before accepting more telemetry.');\n        const changedFrom = Math.min(sequence, this.tapeLog.length);\n        while (this.tapeLog.length <= sequence) {\n            const at = this.tapeLog.length;\n            this.tapeLog.push({ version: 1, sequence: at, simTimeMs: at * 400, durationMs: 400,\n                activity: .12, coherence: .25, attention: 0, channel: 'other', observed: 0, roamX: 0, roamY: 0, flip: 1, lit: 1,\n                onsets: Array(13).fill(0), activeMs: Array(13).fill(0), errors: 0, agentIds: [], waiting: false });\n        }\n        this.tapeLog[sequence] = { ...structuredClone(input), sequence, simTimeMs: sequence * 400 };\n        this.hashTape(changedFrom);\n    }\n    /** dt is bounded so suspending a surface cannot cause an unbounded catch-up. */\n    step(dt, opts = { motion: true, sensitivity: 1 }) {\n        if (!Number.isFinite(dt) || dt < 0 || dt > 10)\n            throw new Error('World dt must be in [0, 10] seconds.');\n        this.accumulator += dt;\n        this.voices = [];\n        while (this.accumulator + 1e-10 >= 1 / HZ) {\n            this.accumulator -= 1 / HZ;","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/ios/Resources/pet-native.js#L432-L468","documentation":"PetWorld's `tapeLog` is a fixed-capacity in-memory recording of pet telemetry frames; when the incoming sequence number reaches 216,000 (the hardcoded archive threshold), the world refuses to append more entries. The library throws this to force callers to offload/persist older frames instead of letting the buffer grow unbounded in the iOS native bridge.","triggerScenarios":"Calling the recording/append API of `PetWorld` (public) with a sequence number >= 216,000 — e.g. continuously feeding frames for a long-running simulation without ever trimming or archiving `tapeLog`, or inserting at a large sequence index directly.","commonSituations":"Long-lived pet sessions (216,000 frames at 400 ms sim-time each is ~24 hours of continuous telemetry) where the app never rotates the tape; replay tooling that seeds a huge starting sequence; clock/simulator drift pushing sequences past the cap.","solutions":["Archive (persist and clear) the legacy recording before the sequence reaches 216,000 — rotate `tapeLog` in your session lifecycle, e.g. dump to disk and start a new PetWorld with sequence 0.","Check `world.tapeLog.length` (or your current sequence) on a timer or per-step and trigger archiving below the threshold, e.g. at 200,000 frames.","For replay/testing, clamp or remap sequence numbers to stay below the cap instead of feeding raw counters."],"exampleFix":"// before\nworld.record(nextSequence, frame); // nextSequence grows past 216_000 -> throws\n// after\nif (nextSequence >= 200_000) {\n  archiveTape(world.tapeLog);      // persist legacy recording\n  world = new PetWorld();          // restart at sequence 0\n}\nworld.record(nextSequence, frame);","handlingStrategy":"validation","validationCode":"function canAcceptSequence(seq) { return Number.isSafeInteger(seq) && seq >= 0 && seq < 216_000; }","typeGuard":null,"tryCatchPattern":"try { world.record(seq, frame); } catch (e) { if (e.message.includes('Archive the legacy recording')) { archiveTape(world.tapeLog); world = new PetWorld(); } else throw e; }","preventionTips":["Track tapeLog length and archive at a soft threshold (e.g. 200,000 frames) before hitting the hard cap.","Run long-session soak tests that exceed 216,000 frames to prove rotation works.","Never feed raw unbounded counters as sequence numbers."],"tags":["capacity","telemetry","resource-limit","javascript"],"backgroundTag":"value-out-of-range","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}