Hmbown/CodeWhale · error · Error
Pet tape exceeds 24 hours.
Error message
Pet tape exceeds 24 hours.
What it means
decodePetJSONL() parses a persisted 'pet tape' (JSONL of pet buckets) and enforces hard limits: the tape may cover at most 216,000 one-second buckets, i.e. 24 hours of data. If the decoded tape holds more rows than that, the parser refuses it rather than loading an oversized tape.
Solutions
- Rotate or truncate the tape file so it holds at most 216,000 rows (24 hours of 1-second buckets).
- Split the tape into per-day files and decode each segment separately.
- Raise the 216_000 cap only if 1-second bucketing assumptions genuinely changed — otherwise keep the limit.
- Export the tape to a compacted/downsampled format before decoding.
Example fix
// before
decodePetJSONL(fs.readFileSync('pet-tape.jsonl', 'utf8')); // throws on >216k rows
// after
const rows = fs.readFileSync('pet-tape.jsonl', 'utf8').trim().split('\n');
const last24h = rows.slice(-216_000).join('\n');
decodePetJSONL(last24h); Defensive patterns
Strategy: validation
Validate before calling
function canDecodeTape(text) {
const rows = text.split(/\r?\n/).filter(l => l.trim());
return rows.length <= 216_000;
}
if (!canDecodeTape(raw)) raw = raw.split('\n').slice(-216_000).join('\n'); Type guard
function isWithinTapeCapacity(rows) {
return Array.isArray(rows) && rows.length <= 216_000;
} Try / catch
try {
const tape = decodePetJSONL(raw);
} catch (e) {
if (e.message.includes('exceeds 24 hours')) {
const tail = raw.split(/\r?\n/).filter(Boolean).slice(-216_000).join('\n');
const tape = decodePetJSONL(tail);
} else throw e;
} Prevention
- Rotate the tape file daily (24h of 1-second buckets = 216,000 rows max).
- Check row count with wc -l before decoding.
- Never append across sessions into one tape file.
- Downsample to coarser buckets for periods longer than 24 hours.
When it happens
Trigger: Calling decodePetJSONL (directly or via the pet-watch tape loader) on a JSONL file whose non-empty line count exceeds 216,000 — e.g. a tape was appended to for more than 24 hours, or an earlier run wrote without rotation.
Common situations: Long-running pet-watch sessions that never rotate the tape file; clock/timezone changes inflating bucket counts; a merged or concatenated tape from several sessions.
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
- Live pet input exceeds its tail limit.
- Non-contiguous pet tape.
- Pet input exceeds 250000 events.
- artifact id and extension must contain safe ASCII characters
- bounded provider catalog cache exceeds its write limit
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/bd62b7701409553c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/pet_watch/pet-native.js:1118
exports.PET_BIN_MS = 400;
function validatePetBucket(value) {
(0, pet_sim_js_1.validatePetState)(value);
const b = value;
if (!b || typeof b !== 'object' || b.version !== 1 || !Number.isSafeInteger(b.sequence) || b.sequence < 0 || b.sequence > pet_sim_js_1.PET_MAX_SECONDS * 2.5
|| b.simTimeMs !== b.sequence * exports.PET_BIN_MS || b.durationMs !== exports.PET_BIN_MS
|| !model_js_1.CATEGORIES.includes(b.channel) || 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.');
}
function decodePetJSONL(text) {
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));
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. */
class PetLiveTape {
sequence;
reset() { this.sequence = undefined; }
readTail(text) {
if (!text) {
this.reset();
return;
}
if (text.length > 262_144) {
this.reset();
throw new Error('Live pet input exceeds its tail limit.');View on GitHub (pinned to 73e0f67d83)