copy/v86 · error · StateLoadError
Invalid length:
Error message
Invalid length:
What it means
read_state_header validates saved-state buffers before any restore. A state buffer shorter than STATE_INFO_BLOCK_START cannot even contain the mandatory header, so a StateLoadError('Invalid length: N') is thrown reporting the actual byte length received.
Source
Thrown at src/state.js:210
dbg_log("State: json size " + (info_block.byteLength >> 10) + "k");
dbg_log("State: Total buffers size " + (buffer_block.byteLength >> 10) + "k");
return result;
}
/* @param {CPU} cpu */
export function restore_state(cpu, state)
{
state = new Uint8Array(state);
function read_state_header(state, check_length)
{
const len = state.length;
if(len < STATE_INFO_BLOCK_START)
{
throw new StateLoadError("Invalid length: " + len);
}
const header_block = new Int32Array(state.buffer, state.byteOffset, 4);
if(header_block[STATE_INDEX_MAGIC] !== STATE_MAGIC)
{
throw new StateLoadError("Invalid header: " + h(header_block[STATE_INDEX_MAGIC] >>> 0));
}
if(header_block[STATE_INDEX_VERSION] !== STATE_VERSION)
{
throw new StateLoadError(
"Version mismatch: dump=" + header_block[STATE_INDEX_VERSION] +
" we=" + STATE_VERSION);
}
if(check_length && header_block[STATE_INDEX_TOTAL_LEN] !== len)
{View on GitHub (pinned to 180830d539)
Solutions
- Check state.byteLength >= STATE_INFO_BLOCK_START (and nonzero) before calling the restore API
- Re-export/re-download the state file and verify its size matches the original dump
- Ensure the file/URL actually serves the v86 state binary, not an error page (check content-type/size)
- Restore from a known-good backup state
Example fix
// before
emulator.restore_state(stateBuffer); // throws if truncated
// after
const STATE_INFO_BLOCK_START = 12;
if (!stateBuffer || stateBuffer.byteLength < STATE_INFO_BLOCK_START) {
throw new Error("state file too small/truncated: " + (stateBuffer?.byteLength ?? 0));
}
emulator.restore_state(stateBuffer); Defensive patterns
Strategy: validation
Validate before calling
function isPlausibleState(buf) {
return buf instanceof Uint8Array && buf.byteLength >= 12; // >= STATE_INFO_BLOCK_START
}
if (!isPlausibleState(state)) throw new Error("state truncated/empty: " + (state?.byteLength ?? 0)); Type guard
function isStateBuffer(x) {
return x instanceof Uint8Array && x.byteLength >= 12;
} Try / catch
try {
emulator.restore_state(state);
} catch (e) {
if (e instanceof StateLoadError && /Invalid length/.test(e.message)) {
promptUserToReexportState();
} else throw e;
} Prevention
- Check file size > 0 and ≥ header size before restore
- Verify downloads completed (content-length comparison)
- Never save states from error-page responses
- Keep verified backups of important states
When it happens
Trigger: Calling restore_state/state load APIs with a Uint8Array whose byteLength < STATE_INFO_BLOCK_START — e.g. an empty or truncated file, reading a URL that returned an error page, or passing the wrong (much smaller) buffer.
Common situations: Downloaded state file truncated (network error, interrupted download); server returned an HTML 404/500 page saved as the state file; user picked the wrong file; state loaded from localStorage that was never written.
Related errors
- Length doesn't match header: real=... header=...
- Invalid header:
- Invalid info block length:
- Version mismatch: dump=... we=...
AI-assisted analysis of copy/v86@180830d539 (2026-08-31).
Data as JSON: /api/errors/82d792a399bc3b9f.
Report an issue: GitHub.