nautechsystems/nautilus_trader · error
Buffer too short for SBE header: expected {HEADER_LEN}, was
Error message
Buffer too short for SBE header: expected {HEADER_LEN}, was {} What it means
decode_execution_report parses a binary SBE-encoded Binance Spot execution report. SBE frames begin with a fixed-size header (block length, template ID, schema ID, version); if the input buffer is shorter than HEADER_LEN it cannot even be interpreted as a header, so decoding bails immediately.
Source
Thrown at crates/adapters/binance/src/spot/websocket/trading/decode_sbe.rs:64
"symbol",
"client_order_id",
"orig_client_order_id",
"commission_asset",
"reject_reason",
"counter_symbol",
];
/// Decodes an SBE ExecutionReportEvent (template 603) into a [`BinanceSpotExecutionReport`].
///
/// The input buffer must include the 8-byte SBE message header.
///
/// # Errors
///
/// Returns error if the buffer is too short, the template ID is wrong,
/// the schema ID does not match, or variable-length data is malformed.
pub fn decode_execution_report(data: &[u8]) -> anyhow::Result<BinanceSpotExecutionReport> {
if data.len() < HEADER_LEN {
anyhow::bail!(
"Buffer too short for SBE header: expected {HEADER_LEN}, was {}",
data.len()
);
}
let buf = ReadBuf::new(data);
let block_length = buf.get_u16_at(0);
let template_id = buf.get_u16_at(2);
let schema_id = buf.get_u16_at(4);
let version = buf.get_u16_at(6);
if template_id != execution_report_event_codec::SBE_TEMPLATE_ID {
anyhow::bail!(
"Wrong template ID: expected {}, received {template_id}",
execution_report_event_codec::SBE_TEMPLATE_ID
);
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Check data.len() in the message against HEADER_LEN to see how short the buffer is — a tiny length (e.g. <10 bytes) usually means the wrong payload type was passed.
- Verify the WS message routing: only trading (SBE) binary frames should reach this decoder, not public JSON text frames.
- Fix frame reassembly so complete messages are delivered to the decoder before invocation.
- If intentional truncation handling is needed, validate data.len() >= HEADER_LEN at the call site first.
Example fix
// before
decode_execution_report(&payload)?;
// after
if payload.len() >= HEADER_LEN {
decode_execution_report(&payload)?;
} else {
log::warn!("skipping short frame: {} bytes", payload.len());
} Defensive patterns
Strategy: validation
Validate before calling
fn is_decodable_sbe_frame(data: &[u8]) -> bool { data.len() >= HEADER_LEN } Try / catch
if data.len() < HEADER_LEN {
log::warn!("short frame ({} bytes), skipping", data.len());
return Ok(None);
}
let report = decode_execution_report(data)?; Prevention
- Route only binary trading-stream frames to the SBE decoder; keep JSON public-stream frames on the JSON parser.
- Reassemble complete WS frames before handing payloads to the decoder.
- Check buffer length against HEADER_LEN at the call site before decoding.
- Validate test fixtures build full SBE messages, not truncated ones.
When it happens
Trigger: decode_execution_report receiving a payload shorter than HEADER_LEN bytes — a truncated WS frame, a text (non-SBE) message passed to the SBE decoder, or an off-by-slice error cutting the message before the full header arrives.
Common situations: Accidentally feeding JSON stream payloads into the SBE trading decoder; network fragmentation/truncation bugs in message reassembly; test fixtures that are intentionally truncated (e.g. test_decode_execution_report_truncated_header) or wrongly built.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- Wrong template ID: expected {execution_report_event_codec::S
- Wrong template ID: expected {outbound_account_position_event
- Symbol '{}' is not trading (status: {})
- WS submit order failed: {e}
- WS cancel order failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b6c7a96fc485636b.
Report an issue: GitHub.