Hmbown/CodeWhale · error · Error
Recording exceeds the 64 MiB export limit. The current…
Error message
Recording exceeds the 64 MiB export limit. The current world was kept.
What it means
Thrown by the save/export handler while incrementally serializing `world.recordingChunk(index)` chunks and accumulating their UTF-8 byte size. If the accumulated recording exceeds 64 MiB the export is aborted; the live world is untouched because the catch handler only updates the message text.
Solutions
- Shorten the session or reset the recording before exporting.
- Trim or sample the recorded tape to reduce size under the limit.
- Split the recording and export in parts if long captures are required.
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
let bytes = 0;
for (let i = 0; ; i++) { const c = world.recordingChunk(i); if (c === null) break; bytes += new TextEncoder().encode(c).length; }
if (bytes > 64 * 1024 * 1024) trimRecording(); Type guard
null
Try / catch
try { exportRecording(); } catch (e) { message.textContent = e.message; /* world remains usable */ } Prevention
- Periodically reset or trim long recordings.
- Estimate export size before clicking save on marathon sessions.
- Warn users when the recording approaches the 64 MiB limit.
When it happens
Trigger: Clicking the `save` button after a recording has grown past 64 MiB of serialized JSON chunk data (long-running sessions with dense telemetry).
Common situations: Leaving the pet running for hours with a large tape; high-frequency interaction recording; exporting after importing a near-limit replay and letting it grow.
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
- artifact tree exceeds export depth limit
- artifact tree exceeds export entry limit
- bounded provider catalog cache exceeds its write limit
- bundle at is bytes; the limit is bytes
- Cannot export a root model alias into a non-table provider…
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/e4df04bd749ff67d.
Report an issue: GitHub.
Appendix: source
Thrown at pet/src/ui/pet.ts:217
const traces = importTrace(text, file.name, { privacy: 'metadata' });
if (traces.length !== 1) throw new Error('Choose one recording to import.');
nextTape = compilePetTelemetry(traces[0].events, traces[0].duration);
}
next = new PetWorld(points, nextTape, [], 2, true);
}
if (!await mayLeave()) return;
adoptImported(next, `Local replay · ${file.name}`);
message.textContent = 'Recording loaded locally, including its current pose, interactions and score.';
} catch (error) { message.textContent = error instanceof Error ? error.message : 'Unable to import this file.'; }
finally { input.value = ''; }
};
get('save').onclick = () => {
try {
const chunks: string[] = []; let bytes = 0;
for (let index = 0; ; index++) {
const chunk = world.recordingChunk(index); if (chunk === null) break;
bytes += new TextEncoder().encode(chunk).length;
if (bytes > 64 * 1024 * 1024) throw new Error('Recording exceeds the 64 MiB export limit. The current world was kept.');
chunks.push(chunk);
}
const blob = new Blob(chunks, { type: 'application/json' });
const url = URL.createObjectURL(blob), a = document.createElement('a'); a.href = url; a.download = 'codewhale-pet-replay.json'; a.click(); setTimeout(() => URL.revokeObjectURL(url), 1000);
} catch (error) { message.textContent = error instanceof Error ? error.message : 'Unable to export the recording. The current world was kept.'; }
};
get('follow').onclick = async () => {
// A browser-granted read handle is the same local JSONL seam native hosts use.
// It is never persisted: reloading restores the accepted recording, not access.
const picker = (window as Window & { showOpenFilePicker?: () => Promise<{ getFile(): Promise<File> }[]> }).showOpenFilePicker;
if (!picker) { message.textContent = 'This browser cannot follow local files. Import a tape to replay it, or use the native pet for live telemetry.'; return; }
try {
const [handle] = await picker.call(window); if (!handle) return;
const file = await handle.getFile();
if (!await mayLeave()) return;
stopFollowing(); const ticket = liveGeneration;
mode.value = 'live'; paused = false; get('pause').textContent = 'Pause'; get('pause').setAttribute('aria-pressed', 'false');
get<HTMLButtonElement>('pause').disabled = true; seek.disabled = true;View on GitHub (pinned to 433685b202)