Hmbown/CodeWhale · error · Error
Pet tape exceeds 24 hours.
Error message
Pet tape exceeds 24 hours.
What it means
Thrown by decodePetJSONL when the tape contains more than 216,000 non-empty JSONL rows. 216,000 rows equals 24 hours at PET_BIN_MS bucket granularity, so this guard rejects a tape that would represent more than one day of telemetry and would break downstream bucket/sequence assumptions.
Solutions
- Rotate the tape daily at the writer and decode one day at a time
- Split the text into ≤216k-row chunks and decode each batch separately
- Deduplicate rows before decoding if duplication inflated the count
- Archive older days instead of concatenating them into one tape
Example fix
// before
const all = decodePetJSONL(weekOfTapes);
// after
const days = weekOfTapes.split('\n---DAY---\n');
const all = days.flatMap(day => decodePetJSONL(day)); Defensive patterns
Strategy: validation
Validate before calling
const rowCount = text.split(/\r?\n/).filter(l => l.trim()).length;
if (rowCount > 216_000) throw new Error('Tape spans more than 24h; split before decoding'); Type guard
null
Try / catch
try {
buckets = decodePetJSONL(text);
} catch (e) {
if (e.message === 'Pet tape exceeds 24 hours.') {
buckets = splitIntoDays(text).flatMap(decodePetJSONL);
} else throw e;
} Prevention
- Rotate the tape at the writer every 24h / 216k bins
- Deduplicate rows before decoding
- Never concatenate multiple days into one decode call
When it happens
Trigger: Calling decodePetJSONL on a JSONL string that splits into more than 216,000 non-empty lines — e.g. a file accumulated over multiple days without rotation.
Common situations: Writer never rotates the daily tape; the loader was pointed at an aggregate/merged file; a bug duplicated rows so the count blew past the cap.
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
- Pet tape exceeds 24 hours.
- Invalid pet duration.
- Invalid pet duration.
- Live pet input exceeds its tail limit.
- Pet input exceeds 250000 events.
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/a84d654151e61259.
Report an issue: GitHub.
Appendix: source
Thrown at pet/src/core/pet-telemetry.ts:36
}
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;
let packet: unknown;
try { packet = JSON.parse(line); validatePetBucket(packet); }View on GitHub (pinned to 433685b202)