Hmbown/CodeWhale · error · Error

Archive this pet recording before accepting more telemetry.

Error message

Archive this pet recording before accepting more telemetry.

What it means

acceptTelemetry() appends one 400ms PetBucket per call into an in-memory tapeLog, and this throw caps that tape at 216,000 buckets (24 hours at 400ms per bucket). The limit keeps the host's replay tape bounded, so callers must archive the recording (persist and start a fresh PetWorld) before continuing.

Solutions

  1. Serialize/archive the current recording (export the tape + interactions) and start a fresh PetWorld before calling acceptTelemetry again.
  2. Detect the limit proactively by checking the tape length before accepting more packets.
  3. Rotate recordings at a smaller interval (e.g. hourly) so the 24h cap is never approached.
  4. If replaying, verify you are not double-feeding buckets into a restored world.

Example fix

// before
world.acceptTelemetry(bucket); // throws once tape is full
// after
if (world.isFull?.() ?? false) archive(world);
world.acceptTelemetry(bucket);
Defensive patterns

Strategy: try-catch

Validate before calling

if (world.tapeLog?.length >= 216_000) archiveAndRotate(world);

Type guard

function canAcceptTelemetry(world): boolean { return Array.isArray(world.tapeLog) && world.tapeLog.length < 216_000; }

Try / catch

try { world.acceptTelemetry(bucket); } catch (e) { if (/Archive this pet recording/.test(e.message)) { await archive(world); world = new PetWorld(...); world.acceptTelemetry(bucket); } else throw e; }

Prevention

When it happens

Trigger: Calling acceptTelemetry() when this.tapeLog.length has reached 216,000 entries — i.e. continuously feeding live telemetry into one PetWorld instance for a full 24 simulated hours without archiving.

Common situations: A long-running session that keeps a single PetWorld alive for a day of continuous telemetry; a host that never rotates recordings; a replay/restore that re-accepts buckets on top of an already-full tape.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/a22f46699488a97f. Report an issue: GitHub.

Appendix: source

Thrown at pet/src/core/pet-world.ts:293

    this.voices = [];
  }

  /** Branch at the current playhead; input is journalled for the next fixed tick.
   * A live touch never needs to re-simulate the creature's entire lifetime. */
  interact(kind: PetInteraction['kind'], x: number, y: number): void {
    if (!['attention', 'food'].includes(kind) || !Number.isFinite(x) || !Number.isFinite(y) || Math.abs(x) > 1 || Math.abs(y) > 1)
      throw new Error('Invalid pet interaction.');
    if (this.branchTick !== this.tick) this.interactionLog.splice(this.interactionIndex);
    this.branchTick = this.tick;
    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: PetBucket): void {
    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);

View on GitHub (pinned to 433685b202)