Hmbown/CodeWhale · error · Error
Pet archive numbering is exhausted; existing files were…
Error message
Pet archive numbering is exhausted; existing files were preserved.
What it means
Thrown while scanning the recording directory for existing `.segment-NNNNNN.jsonl` archives when a suffix encodes a segment number at or above Number.MAX_SAFE_INTEGER. The recorder refuses to keep incrementing numbering because it could no longer represent the next segment number safely, and aborts without touching existing files.
Solutions
- Find the offending file: `ls | grep -E 'segment-[0-9]{6,}\.jsonl$'` and inspect its numeric suffix.
- Rename or remove the file with the out-of-range number (it is not a real archive this recorder created).
- If it is genuine history, renumber segments into the safe range and update any references.
- Retry creating the recorder after cleanup.
Example fix
// before: bogus file in recording dir pet-recording.segment-99999999999999999999.jsonl // after: remove or renumber mv pet-recording.segment-99999999999999999999.jsonl /tmp/quarantine/
Defensive patterns
Strategy: validation
Validate before calling
import { readdir } from 'node:fs/promises';
const dir = dirname(recordingPath);
const bad = (await readdir(dir)).filter(n => /^\.segment-|segment-[0-9]{7,}\.jsonl$/.test(n));
if (bad.some(n => Number(n.match(/segment-([0-9]+)\./)[1]) >= Number.MAX_SAFE_INTEGER)) {
throw new Error(`clean up out-of-range segment files: ${bad.join(', ')}`);
} Prevention
- Do not hand-create files matching `<name>.segment-*.jsonl` in the recording directory
- Quarantine stray/huge-numbered segment files before starting the recorder
- Keep segment numbering below Number.MAX_SAFE_INTEGER (real usage never approaches it)
When it happens
Trigger: A directory containing a file named `<basename>.segment-9007199254740991.jsonl` or larger (7+ digits beyond the safe range) when the recorder initializes; also a manually created or corrupted segment file with an absurd number.
Common situations: Hand-crafted or test files that match the segment pattern with a huge numeric suffix; corrupted directory contents from a previous misbehaving tool.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- already exists; pass --force to overwrite it
- Android loaded image
- application not found or name is ambiguous in the AT-SPI…
- approval log has no parent
- artifact name is not portable UTF-8
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/1c2b1a5077896cd0.
Report an issue: GitHub.
Appendix: source
Thrown at pet/scripts/lib/pet-recorder.mjs:91
length += bytesRead;
}
if (length !== Number(held.size)) throw new Error('The previous pet recording changed while reading; it was preserved.');
const text = new TextDecoder('utf-8', { fatal: true }).decode(contents.subarray(0, length));
if (text && !text.endsWith('\n')) throw new Error('The previous pet recording has an incomplete final row; it was preserved.');
decodePetJSONL(text);
const unchanged = await output.stat({ bigint: true });
if (unchanged.size !== original.size || unchanged.mtimeNs !== original.mtimeNs)
throw new Error('The previous pet recording changed while reading; it was preserved.');
bytes = length; restart = true; expectedMtime = original.mtimeNs;
// Continue archive numbering without collecting a growing directory list.
const prefix = `${basename(path)}.segment-`;
for await (const entry of await opendir(dirname(path))) {
if (!entry.name.startsWith(prefix)) continue;
const suffix = entry.name.slice(prefix.length);
if (!/^[0-9]{6,}\.jsonl$/.test(suffix)) continue;
const number = Number(suffix.slice(0, -6));
if (!Number.isSafeInteger(number) || number >= Number.MAX_SAFE_INTEGER)
throw new Error('Pet archive numbering is exhausted; existing files were preserved.');
segment = Math.max(segment, number);
}
}
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) {View on GitHub (pinned to 433685b202)