nautechsystems/nautilus_trader · error

Buffer too short for fixed block: expected {min_len}, was {}

Error message

Buffer too short for fixed block: expected {min_len}, was {}

What it means

After validating the header, the decoder requires HEADER_LEN + block_length bytes (8-byte header plus the fixed field block). This error means the buffer ends before the fixed block completes, so fixed-width fields would run past the end of the data. The decoder bails instead of performing an out-of-bounds read.

Source

Thrown at crates/adapters/binance/src/spot/websocket/trading/decode_sbe.rs:99

    }

    if schema_id != crate::spot::sbe::spot::SBE_SCHEMA_ID {
        anyhow::bail!(
            "Wrong schema ID: expected {}, received {schema_id}",
            crate::spot::sbe::spot::SBE_SCHEMA_ID
        );
    }

    let min_block_len = execution_report_min_block_length(version);
    if usize::from(block_length) < min_block_len {
        anyhow::bail!(
            "SBE execution report block length too short: expected at least {min_block_len}, was {block_length}"
        );
    }

    let min_len = HEADER_LEN + usize::from(block_length);
    if data.len() < min_len {
        anyhow::bail!(
            "Buffer too short for fixed block: expected {min_len}, was {}",
            data.len()
        );
    }

    let mut field_offset = min_len;
    for field in EXECUTION_REPORT_VAR_DATA_FIELDS {
        let Some(length) = data.get(field_offset) else {
            anyhow::bail!(
                "Buffer too short for {field} length: expected {}, was {}",
                field_offset + 1,
                data.len()
            );
        };
        let expected_len = field_offset + 1 + usize::from(*length);
        if data.len() < expected_len {
            anyhow::bail!(
                "Buffer too short for {field}: expected {expected_len}, was {}",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the complete SBE frame (header + full fixed block + var-length fields) is passed to the decoder
  2. Fix stream reassembly so fragmented WebSocket messages are joined before decoding
  3. Include the 8-byte SBE message header when slicing the payload
  4. Re-capture or regenerate truncated test fixtures

Example fix

// before
let report = decode_execution_report(&payload[8..])?; // header stripped twice
// after
let report = decode_execution_report(&payload)?; // decoder expects header included
Defensive patterns

Strategy: validation

Validate before calling

pub fn frame_complete(data: &[u8]) -> bool {
    if data.len() < 8 { return false; }
    let block_length = u16::from_be_bytes([data[0], data[1]]) as usize;
    data.len() >= 8 + block_length
}

Type guard

fn complete_frame<'a>(data: &'a [u8]) -> Option<&'a [u8]> {
    (data.len() >= 8 && {
        let bl = u16::from_be_bytes([data[0], data[1]]) as usize;
        data.len() >= 8 + bl
    }).then_some(data)
}

Try / catch

match decode_execution_report(&frame) {
    Ok(r) => handle(r),
    Err(e) if e.to_string().contains("Buffer too short") => buffer_for_reassembly(&frame),
    Err(e) => log::warn!("SBE decode failed: {e}"),
}

Prevention

When it happens

Trigger: Calling decode_execution_report with a slice shorter than 8 + block_length bytes — e.g. a WebSocket message split across frames and naively concatenated, a partially written capture file, or slicing a buffer with the wrong offset/length.

Common situations: Incorrect frame framing/reassembly in the WebSocket layer; reading binary logs with a wrong record boundary; tests passing only the body without the 8-byte SBE header.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/395456b51b798bbb. Report an issue: GitHub.