copy/v86 · error · StateLoadError

Invalid info block length:

Error message

Invalid info block length: 

What it means

restore_state reads the info-block length from the header and sanity-checks it: it must be non-negative and the info block must fit inside the state buffer (info_block_len + 12 < state.length). Out-of-range values mean the header or dump is corrupted, so StateLoadError('Invalid info block length: N') is thrown before the info block is parsed.

Source

Thrown at src/state.js:314

                buffers.push(cpu.wasm_memory.buffer.slice(offset, offset + buffer_info.length));
                cpu.zstd_read_free(ptr, front_padding + buffer_info.length);
            }

            position += front_padding + buffer_info.length;
        }

        state_object = restore_buffers(state_object, buffers);
        cpu.set_state(state_object);

        cpu.zstd_free_ctx(ctx);
    }
    else
    {
        const info_block_len = read_state_header(state, true);

        if(info_block_len < 0 || info_block_len + 12 >= state.length)
        {
            throw new StateLoadError("Invalid info block length: " + info_block_len);
        }

        const info_block_buffer = state.subarray(STATE_INFO_BLOCK_START, STATE_INFO_BLOCK_START + info_block_len);
        const info_block_obj = read_info_block(info_block_buffer);
        let state_object = info_block_obj["state"];
        const buffer_infos = info_block_obj["buffer_infos"];
        let buffer_block_start = STATE_INFO_BLOCK_START + info_block_len;
        buffer_block_start = buffer_block_start + 3 & ~3;

        const buffers = buffer_infos.map(buffer_info => {
            const offset = buffer_block_start + buffer_info.offset;
            return state.buffer.slice(offset, offset + buffer_info.length);
        });

        state_object = restore_buffers(state_object, buffers);
        cpu.set_state(state_object);
    }
}

View on GitHub (pinned to 180830d539)

Solutions

  1. Discard and re-capture the state file — a corrupt header usually can't be repaired safely
  2. Re-download the state and verify a checksum against the source
  3. Check that the buffer wasn't modified/sliced between capture and restore in your app
  4. Ensure the state was saved by a compatible emulator version (see version checks)

Example fix

// before
emulator.restore_state(corruptState); // throws deep inside
// after
try {
    emulator.restore_state(state);
} catch (e) {
    if (String(e).includes("Invalid info block length")) {
    recoverFromBackupState();
    }
}
Defensive patterns

Strategy: validation

Validate before calling

function infoBlockFits(buf) {
    if (!(buf instanceof Uint8Array) || buf.byteLength < 12) return false;
    const infoLen = new Int32Array(buf.buffer, buf.byteOffset, 4)[2]; // STATE_INDEX_INFO_LEN
    return infoLen >= 0 && infoLen + 12 < buf.byteLength;
}
if (!infoBlockFits(state)) throw new Error("corrupt state header");

Try / catch

try {
    emulator.restore_state(state);
} catch (e) {
    if (e instanceof StateLoadError && /Invalid info block length/.test(e.message)) {
    restoreFromBackup(); // header is corrupt, not repairable
    } else throw e;
}

Prevention

When it happens

Trigger: restore_state called with a state whose header STATE_INDEX_INFO_LEN is negative (int32 overflow/corruption) or so large the info block would run past the end of the buffer — corrupted header bytes, bit-flips in storage, or a hand-crafted/mis-sliced buffer.

Common situations: Bit rot or corruption in stored state files (disk, cloud sync); states manipulated by external tools; memory corruption between capture and restore in the same page (rare).

Related errors


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