Hmbown/CodeWhale · error · Error
Archive the legacy recording before accepting more…
Error message
Archive the legacy recording before accepting more telemetry.
What it means
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.
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.
Example fix
// before
world.record(nextSequence, frame); // nextSequence grows past 216_000 -> throws
// after
if (nextSequence >= 200_000) {
archiveTape(world.tapeLog); // persist legacy recording
world = new PetWorld(); // restart at sequence 0
}
world.record(nextSequence, frame); Defensive patterns
Strategy: validation
Validate before calling
function canAcceptSequence(seq) { return Number.isSafeInteger(seq) && seq >= 0 && seq < 216_000; } Try / catch
try { world.record(seq, frame); } catch (e) { if (e.message.includes('Archive the legacy recording')) { archiveTape(world.tapeLog); world = new PetWorld(); } else throw e; } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Archive the legacy recording before accepting more…
- Archive this pet recording before accepting more telemetry.
- Invalid failure observation time.
- Invalid pet state.
- Pet Engine observation window is full.
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/5bda3c35af8de8d9.
Report an issue: GitHub.
Appendix: source
Thrown at pet/ios/Resources/pet-native.js:450
this.interactionLog.push({ timeMs: (this.tick + 1) * 1000 / HZ, kind, x, y });
}
/** Accept a live source packet at the next 400ms boundary. The accepted tape,
* including any missing intervals, is the exact replay authority for this host. */
acceptTelemetry(input) {
(0, pet_telemetry_js_1.validatePetBucket)(input);
const sequence = Math.floor(this.tick / 12) + 1;
if (this.tapeLog.length >= 216_000)
throw new Error('Archive this pet recording before accepting more telemetry.');
this.hasTelemetry = true;
if (this.segmented) {
const at = this.tapeLog.findIndex(b => b.sequence >= sequence);
const index = at < 0 ? this.tapeLog.length : at;
this.tapeLog.splice(index, at >= 0 && this.tapeLog[at].sequence === sequence ? 1 : 0, { ...structuredClone(input), sequence, simTimeMs: sequence * 400 });
this.hashTape(index);
return;
}
if (sequence >= 216_000)
throw new Error('Archive the legacy recording before accepting more telemetry.');
const changedFrom = Math.min(sequence, this.tapeLog.length);
while (this.tapeLog.length <= sequence) {
const at = this.tapeLog.length;
this.tapeLog.push({ version: 1, sequence: at, simTimeMs: at * 400, durationMs: 400,
activity: .12, coherence: .25, attention: 0, channel: 'other', observed: 0, roamX: 0, roamY: 0, flip: 1, lit: 1,
onsets: Array(13).fill(0), activeMs: Array(13).fill(0), errors: 0, agentIds: [], waiting: false });
}
this.tapeLog[sequence] = { ...structuredClone(input), sequence, simTimeMs: sequence * 400 };
this.hashTape(changedFrom);
}
/** dt is bounded so suspending a surface cannot cause an unbounded catch-up. */
step(dt, opts = { motion: true, sensitivity: 1 }) {
if (!Number.isFinite(dt) || dt < 0 || dt > 10)
throw new Error('World dt must be in [0, 10] seconds.');
this.accumulator += dt;
this.voices = [];
while (this.accumulator + 1e-10 >= 1 / HZ) {
this.accumulator -= 1 / HZ;View on GitHub (pinned to 433685b202)