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

  1. Check state.byteLength >= STATE_INFO_BLOCK_START (and nonzero) before calling the restore API
  2. Re-export/re-download the state file and verify its size matches the original dump
  3. Ensure the file/URL actually serves the v86 state binary, not an error page (check content-type/size)
  4. 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

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


AI-assisted analysis of copy/v86@180830d539 (2026-08-31). Data as JSON: /api/errors/82d792a399bc3b9f. Report an issue: GitHub.