copy/v86 · error · StateLoadError
Length doesn't match header: real=... header=...
Error message
Length doesn't match header: real=... header=...
What it means
The header records STATE_INDEX_TOTAL_LEN, the exact byte length the dump had when written. When check_length is true, read_state_header compares it with the actual buffer length and throws StateLoadError('Length doesn't match header: real=N header=M') on any mismatch, catching truncated, padded, or concatenated state buffers.
Source
Thrown at src/state.js:229
}
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)
{
throw new StateLoadError(
"Length doesn't match header: " +
"real=" + len + " header=" + header_block[STATE_INDEX_TOTAL_LEN]);
}
return header_block[STATE_INDEX_INFO_LEN];
}
function read_info_block(info_block_buffer)
{
const info_block = new TextDecoder().decode(info_block_buffer);
return JSON.parse(info_block);
}
if(new Uint32Array(state.buffer, 0, 1)[0] === ZSTD_MAGIC)
{
const ctx = cpu.zstd_create_ctx(state.length);
new Uint8Array(cpu.wasm_memory.buffer, cpu.zstd_get_src_ptr(ctx) >>> 0, state.length).set(state);View on GitHub (pinned to 180830d539)
Solutions
- Verify the state file size matches what was originally saved (compare with the header value printed in the error)
- Re-download/re-export the state file completely and retry
- If the state is embedded in a larger blob, slice exactly the header-reported length
- Check the storage/transfer path for corruption (compare checksums before and after)
Example fix
// before emulator.restore_state(bigBlob.subarray(offset)); // length may not match header // after const headerLen = new Int32Array(bigBlob.buffer, bigBlob.byteOffset, 4)[3]; emulator.restore_state(bigBlob.subarray(offset, offset + headerLen));
Defensive patterns
Strategy: validation
Validate before calling
function headerLengthMatches(buf) {
if (!(buf instanceof Uint8Array) || buf.byteLength < 12) return false;
const h = new Int32Array(buf.buffer, buf.byteOffset, 4);
return h[3] === buf.byteLength; // STATE_INDEX_TOTAL_LEN === len
}
if (!headerLengthMatches(state)) throw new Error("state file size mismatch"); Try / catch
try {
emulator.restore_state(state);
} catch (e) {
if (e instanceof StateLoadError && /Length doesn't match header/.test(e.message)) {
reacquireStateFile(); // re-download / re-export
} else throw e;
} Prevention
- Compare file sizes (or checksums) after download/transfer
- Slice embedded states using the header-reported total length
- Avoid localStorage/IndexedDB paths that may alter blob sizes
- Verify transfer integrity with checksums
When it happens
Trigger: Passing a Uint8Array to restore_state whose byteLength differs from the value stored at STATE_INDEX_TOTAL_LEN in the dump header — truncated download, extra bytes appended, slicing the wrong range out of a bigger blob, or byte-level corruption of the header.
Common situations: Interrupted downloads/partial uploads of state files; storage layers (localStorage, IndexedDB) altering or clipping blobs; manually slicing states out of a combined file with off-by-N errors.
Related errors
AI-assisted analysis of copy/v86@180830d539 (2026-08-31).
Data as JSON: /api/errors/43bb142d5b794827.
Report an issue: GitHub.