Hmbown/CodeWhale · error · Error
Live pet input exceeds its tail limit.
Error message
Live pet input exceeds its tail limit.
What it means
PetLiveTape.push() only accepts a bounded tail of live input (256 KiB). If the supplied text chunk exceeds 262,144 bytes it resets the cursor state and throws, because a chunk that large cannot be a bounded tail of recent lines.
Solutions
- Slice the input to the last 262,144 bytes before handing it to the live tape (e.g. text.slice(-262_144)).
- Fix the driver to supply a bounded tail per the PetLiveTape contract and reset the cursor after suspension.
- Poll more frequently so per-chunk deltas stay under the tail limit.
- After the throw, re-attach with a fresh baseline: pass '' first (reset), then feed bounded tails.
Example fix
// before
liveTape.push(fs.readFileSync('pet.log', 'utf8')); // throws when file > 256 KiB
// after
const text = fs.readFileSync('pet.log', 'utf8');
liveTape.push(text.slice(-262_144)); Defensive patterns
Strategy: validation
Validate before calling
function isBoundedTail(text) {
return typeof text === 'string' && Buffer.byteLength(text, 'utf8') <= 262_144;
}
if (!isBoundedTail(chunk)) chunk = chunk.slice(-262_144); Type guard
function isTailSafe(text) {
return typeof text === 'string' && text.length <= 262_144;
} Try / catch
try {
liveTape.push(chunk);
} catch (e) {
if (e.message.includes('tail limit')) {
liveTape.push(''); // reset baseline
liveTape.push(chunk.slice(-262_144));
} else throw e;
} Prevention
- Always slice reads to a bounded tail (last 256 KiB) before pushing.
- Reset the live-tape cursor after suspension or re-attachment, per its contract.
- Poll frequently enough that deltas stay small.
- Never feed the entire file into the live path; the full-file path is decodePetJSONL.
When it happens
Trigger: Calling the live-tape driver (PetLiveTape push/read) with a text chunk longer than 262,144 bytes — e.g. passing the whole log file instead of a recent tail, or a single unbounded read of a fast-growing file.
Common situations: Driver implementation bug reading the entire file on first attach; a tape file that grew huge between polls so a delta read returns everything; passing accumulated buffer instead of the tail slice.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- Pet input exceeds 250000 events.
- Pet tape exceeds 24 hours.
- response exceeds size limit
- Runtime event frame exceeds the size limit
- Antigravity cloud-code is stream-only; blocking…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/3ae83142ef552faa.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/pet_watch/pet-native.js:1136
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.');
}
if (!text.endsWith('\n'))
return;
const line = text.trimEnd().split('\n').at(-1);
if (!line)
return;
let packet;
try {
packet = JSON.parse(line);
validatePetBucket(packet);
}
catch (error) {
this.reset();
throw error;
}
const previous = this.sequence;
this.sequence = packet.sequence;
if (previous === undefined || packet.sequence <= previous)View on GitHub (pinned to 73e0f67d83)