{"record":{"id":"8728b1252229e650","repo":"Hmbown/CodeWhale","slug":"archive-this-pet-recording-before-accepting-more-telemetry-8728b1","errorCode":null,"errorMessage":"Archive this pet recording before accepting more telemetry.","messagePattern":"Archive this pet recording before accepting more telemetry\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/ios/Resources/pet-native.js","lineNumber":440,"sourceCode":"        this.voices = [];\n    }\n    /** Branch at the current playhead; input is journalled for the next fixed tick.\n     * A live touch never needs to re-simulate the creature's entire lifetime. */\n    interact(kind, x, y) {\n        if (!['attention', 'food'].includes(kind) || !Number.isFinite(x) || !Number.isFinite(y) || Math.abs(x) > 1 || Math.abs(y) > 1)\n            throw new Error('Invalid pet interaction.');\n        if (this.branchTick !== this.tick)\n            this.interactionLog.splice(this.interactionIndex);\n        this.branchTick = this.tick;\n        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 };","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/ios/Resources/pet-native.js#L422-L458","documentation":"The tapeLog is the complete replay authority for the pet, capped at 216,000 buckets (24 hours of 400ms buckets). acceptTelemetry() refuses to accept more telemetry once the cap is reached, forcing the host to archive (persist and reset) the recording first so replay state stays bounded and memory does not grow indefinitely.","triggerScenarios":"Calling acceptTelemetry() when tapeLog.length is already 216000 — i.e. a PetWorld has been continuously receiving live packets for a full day (or replayed up to that depth) without archiving.","commonSituations":"A long-running pet session left open past 24 hours; a host that never implements the archive step; batch-importing a large historical recording in one go.","solutions":["Serialize/archive the current PetWorld recording (tapeLog + interaction log + checkpoints), then start or reset the world and continue accepting telemetry there","Check tapeLog.length < 216000 before each acceptTelemetry and archive when approaching the cap (e.g. at 200k)","Increase the archive threshold check in the host loop rather than catching the throw","Split historical imports into chunks and archive between them"],"exampleFix":"// before\nworld.acceptTelemetry(bucket);\n// after\nif (world.tapeLog.length >= 216_000) {\n  archiveRecording(world); // persist tape + interactions\n  world = new PetWorld();   // continue with fresh recording\n}\nworld.acceptTelemetry(bucket);","handlingStrategy":"validation","validationCode":"function ensureCapacity(world) {\n  if (world.tapeLog.length >= 216_000) {\n    archiveRecording(world);\n    return false; // caller must open a fresh PetWorld\n  }\n  return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n  world.acceptTelemetry(bucket);\n} catch (e) {\n  if (e.message.includes('Archive this pet recording')) {\n    archiveRecording(world);\n    world = new PetWorld();\n    world.acceptTelemetry(bucket);\n  } else throw e;\n}","preventionTips":["Archive proactively at a watermark (e.g. 200k buckets), never at the hard cap","Run the capacity check in the same loop that calls acceptTelemetry","Test long-running sessions (>24h) against the archive path","Persist the interaction log and checkpoints alongside tapeLog during archiving"],"tags":["capacity-limit","storage","telemetry"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}