{"record":{"id":"453eae991cb6e498","repo":"Hmbown/CodeWhale","slug":"archive-the-legacy-recording-before-accepting-more-telemetry","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":"warning","filePath":"crates/tui/src/tui/pet_watch/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/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/pet_watch/pet-native.js#L432-L468","documentation":"In legacy (non-segmented) mode the tape is a dense array indexed by sequence, bounded at 216,000 buckets (~24 hours) by design. Once the incoming sequence number reaches that bound, the legacy format can hold no more history, so acceptTelemetry refuses further packets and demands the recording be archived first. This protects the fixed-size legacy replay authority from overflowing.","triggerScenarios":"Calling world.acceptTelemetry(bucket) on a non-segmented world when the computed sequence = floor(tick/12)+1 is >= 216_000 — i.e. after ~24 hours of simulation ticks without archiving or migrating to segmented checkpoints.","commonSituations":"Very old sessions recorded with the v1 checkpoint format kept alive across days; hosts that never migrated to petCheckpointVersion 2; replaying an accelerated simulation that burns through sequences quickly in tests.","solutions":["Archive the legacy recording, then resume in segmented (checkpoint version 2) mode which supports rotation.","Migrate the pet to petCheckpointVersion 2 so future telemetry uses the segmented tape log.","Shorten the session or reset the world once sequence approaches 216,000."],"exampleFix":"// before\nworld.acceptTelemetry(bucket); // throws once sequence >= 216000 in legacy mode\n// after\nif (Math.floor(world.tick / 12) + 1 >= 216000) { world = migrateToSegmented(world); }\nworld.acceptTelemetry(bucket);","handlingStrategy":"try-catch","validationCode":"function legacyTapeAlmostFull(world) {\n  return !world.segmented && Math.floor(world.tick / 12) + 1 >= 216000 - 1000;\n}","typeGuard":"null","tryCatchPattern":"try {\n  world.acceptTelemetry(bucket);\n} catch (e) {\n  if (e.message.startsWith('Archive the legacy recording')) {\n    await archiveLegacyRecording(world);\n    world = migrateToSegmented(world);\n    world.acceptTelemetry(bucket);\n  } else throw e;\n}","preventionTips":["Migrate legacy v1 pets to petCheckpointVersion 2 (segmented) early","Watch the computed sequence number as sessions age","Archive legacy recordings before they reach ~24 h of ticks","Avoid accelerating simulation in long-lived production sessions"],"tags":["capacity","legacy","telemetry"],"backgroundTag":"file-size-limit-exceeded","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"}