Hmbown/CodeWhale · error · Error
Pet bucket exceeds the recording segment byte limit.
Error message
Pet bucket exceeds the recording segment byte limit.
What it means
During rotation the recorder encodes the bucket as the first row of a new segment (sequence 0); if that single encoded row already exceeds the configured max segment byte size, no segment could ever hold it, so it throws before creating any files.
Solutions
- Inspect the bucket payload and shrink oversized fields before appending.
- Increase the recorder's maxBytes segment limit to exceed one encoded row.
- Fix the producer that emits abnormally large buckets (cap string lengths at the source).
- If this is recurring, add a payload-size check in the producer before calling append().
Example fix
// before
createPetRecorder(path, { maxBytes: 64 });
// after
createPetRecorder(path, { maxBytes: 1024 * 1024 }); Defensive patterns
Strategy: validation
Validate before calling
const encoded = JSON.stringify(bucket) + '\n';
if (Buffer.byteLength(encoded) > maxBytes) throw new Error('bucket row exceeds segment limit; shrink payload or raise maxBytes'); Prevention
- Keep maxBytes comfortably larger than your largest possible bucket row
- Cap string fields in pet buckets at the producer
- Re-check limits after changing the bucket schema
- Compute the worst-case encoded row size when configuring maxBytes
When it happens
Trigger: Appending a pet bucket whose JSONL encoding (all fields plus sequence and simTimeMs) is larger than maxBytes; a bucket carrying a very large string field or nested payload that inflates the row.
Common situations: Downsizing maxBytes below the size of already-produced buckets; a bug producing oversized bucket payloads (huge labels/notes); misconfigured segment limit after changing bucket schema.
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
- A pinned task provider requires an explicit model
- agent profile reasoning_effort must be one of: inherit…
- Codewhale credentials path must be a directory
- Custom sub-agent requires a non-empty allowed_tools list
- Failed to update setting: invalid cost currency
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/33f219834a4b8518.
Report an issue: GitHub.
Appendix: source
Thrown at pet/scripts/lib/pet-recorder.mjs:111
}
}
expectedMtime ??= (await output.stat({ bigint: true })).mtimeNs;
} catch (error) { try { await output?.close(); } finally { lock.close(); } throw error; }
return {
async append(bucket) {
if (!output || busy) throw new Error('Pet recorder is closed or already writing.');
validatePetBucket(bucket);
busy = true;
try {
await lock.check();
const held = await output.stat({ bigint: true }), current = await lstat(path, { bigint: true });
if (!current.isFile() || held.dev !== current.dev || held.ino !== current.ino || held.size !== BigInt(bytes) || held.mtimeNs !== expectedMtime)
throw new Error('The live pet recording was changed or replaced externally; existing files were preserved.');
const encode = seq => encodePetJSONL([{ ...bucket, sequence: seq, simTimeMs: seq * PET_BIN_MS }]);
let row = encode(sequence), size = Buffer.byteLength(row);
if (restart || sequence >= maxBuckets || bytes + size > maxBytes) {
row = encode(0); size = Buffer.byteLength(row);
if (size > maxBytes) throw new Error('Pet bucket exceeds the recording segment byte limit.');
const temporary = resolve(dirname(path), `.${basename(path)}.next-${randomUUID()}`);
const archive = `${path}.segment-${String(segment + 1).padStart(6, '0')}.jsonl`;
let next, installed = false, created = false;
try {
next = await open(temporary, 'wx', 0o600); created = true;
await next.writeFile(row); await next.sync();
const nextIdentity = await next.stat({ bigint: true });
await next.close(); next = undefined;
await output.sync();
// link is exclusive: a collision never replaces someone else's
// archive. Persist this name before replacing the live pathname.
await link(path, archive); await syncDirectory(dirname(path));
// Windows can reject replacement while either writer handle is
// open. Both files are synced and the old file is archived first.
await output.close(); output = undefined;
for (let attempt = 0; ; attempt++) {
await lock.check();
const destination = await lstat(path, { bigint: true });View on GitHub (pinned to 433685b202)