Hmbown/CodeWhale · error · Error

Pet tape exceeds 64 MiB.

Error message

Pet tape exceeds 64 MiB.

What it means

Thrown by decodePetJSONL before parsing when the raw JSONL text is larger than 64 MiB (64 * 1024 * 1024 chars). It is an input-size guard: the caller passed a pet tape file whose byte/char length exceeds the accepted ceiling, so decoding is refused up front instead of attempting to split and parse an oversized payload.

Solutions

  1. Split the tape into ≤64 MiB chunks and decode each with decodePetJSONL separately
  2. Rotate or truncate the telemetry file at the writer so a single tape stays under the cap
  3. Stream/parse line-by-line yourself and call validatePetBucket per row instead of decodePetJSONL
  4. Delete or archive old tape files

Example fix

// before
const buckets = decodePetJSONL(fs.readFileSync(tapePath, 'utf8'));
// after
const text = fs.readFileSync(tapePath, 'utf8');
const buckets = text.length <= 64*1024*1024 ? decodePetJSONL(text)
  : text.split('\n').reduce((acc, line) => acc.concat(decodePetJSONL(line + '\n')), []);
Defensive patterns

Strategy: try-catch

Validate before calling

if (text.length > 64 * 1024 * 1024) {
  // split into chunks before calling decodePetJSONL
}
const ok = text.length <= 64 * 1024 * 1024;

Type guard

null

Try / catch

try {
  buckets = decodePetJSONL(text);
} catch (e) {
  if (e.message === 'Pet tape exceeds 64 MiB.') {
    buckets = chunkText(text, 16 * 1024 * 1024).flatMap(decodePetJSONL);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling decodePetJSONL with a tape string whose .length exceeds 67,108,864 characters — e.g. reading an entire multi-day telemetry file into memory.

Common situations: A telemetry file grew past 24h/64MiB because the pet writer never rotated; a user pointed the loader at the wrong (much larger) log; concatenating many days of tapes before decoding.

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/8384854b91f1a150. Report an issue: GitHub.

Appendix: source

Thrown at pet/src/core/pet-telemetry.ts:34

  agentIds: string[];
  waiting: boolean;
}

export function validatePetBucket(value: unknown): asserts value is PetBucket {
  validatePetState(value);
  const b = value as PetBucket;
  if (!b || typeof b !== 'object' || b.version !== 1 || !Number.isSafeInteger(b.sequence) || b.sequence < 0 || b.sequence > PET_MAX_SECONDS * 2.5
    || b.simTimeMs !== b.sequence * PET_BIN_MS || b.durationMs !== PET_BIN_MS
    || !CATEGORIES.includes(b.channel as Category) || typeof b.waiting !== 'boolean'
    || !Array.isArray(b.agentIds) || b.agentIds.length > 250_000 || b.agentIds.some(id => typeof id !== 'string' || !id || id.length > 4096)
    || !Number.isSafeInteger(b.errors) || b.errors < 0 || b.errors > 250_000
    || !Array.isArray(b.onsets) || b.onsets.length !== 13 || b.onsets.some(n => !Number.isSafeInteger(n) || n < 0 || n > 250_000)
    || !Array.isArray(b.activeMs) || b.activeMs.length !== 13 || b.activeMs.some(n => !Number.isFinite(n) || n < 0 || n > 100_000_000))
    throw new Error('Invalid version 1 pet bucket.');
}

export function decodePetJSONL(text: string): PetBucket[] {
  if (text.length > 64 * 1024 * 1024) throw new Error('Pet tape exceeds 64 MiB.');
  const rows = text.split(/\r?\n/).filter(line => line.trim()).map(line => JSON.parse(line) as unknown);
  if (rows.length > 216_000) throw new Error('Pet tape exceeds 24 hours.');
  return rows.map((row, i) => { validatePetBucket(row); if (row.sequence !== i) throw new Error('Non-contiguous pet tape.'); return row; });
}

/** A live file must advance before its contents count as a new observation.
 * Existing bytes, duplicate samples and a restarted sequence establish a
 * baseline; they never replay an old onset or human request. Drivers supply a
 * bounded tail and reset this cursor after suspension or a new attachment. */
export class PetLiveTape {
  private sequence: number | undefined;
  reset(): void { this.sequence = undefined; }
  readTail(text: string): PetBucket | undefined {
    if (!text) { this.reset(); return; }
    if (text.length > 262_144) { this.reset(); throw new Error('Live pet input exceeds its tail limit.'); }
    if (!text.endsWith('\n')) return;
    const line = text.trimEnd().split('\n').at(-1);
    if (!line) return;

View on GitHub (pinned to 433685b202)