nautechsystems/nautilus_trader · error
Buffer too short for {field}: expected {expected_len}, was {
Error message
Buffer too short for {field}: expected {expected_len}, was {} What it means
Each variable-length field in the ExecutionReportEvent is a 1-byte length followed by that many bytes. This error fires when a field's length byte was read but the buffer ends before the field's full data, i.e. data.len() < field_offset + 1 + length. The decoder bails rather than decoding a short string.
Source
Thrown at crates/adapters/binance/src/spot/websocket/trading/decode_sbe.rs:116
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 {}",
data.len()
);
}
field_offset = expected_len;
}
let mut dec = execution_report_event_codec::ExecutionReportEventDecoder::default().wrap(
buf,
HEADER_LEN,
block_length,
version,
);
let price_exp = dec.price_exponent();
let qty_exp = dec.qty_exponent();
let commission_exp = dec.commission_exponent();
View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the entire frame is delivered before decoding (complete WebSocket reassembly)
- Re-encode the message with execution_report_event_codec to regenerate a consistent buffer
- Validate frame completeness (checksum or length accounting) upstream
- Fix capture/replay tooling that clips the final bytes
Example fix
// before let frame = &captured[..captured.len() - 2]; // accidental clip let report = decode_execution_report(frame)?; // after let report = decode_execution_report(captured)?; // full frame preserved
Defensive patterns
Strategy: validation
Validate before calling
pub fn var_fields_intact(data: &[u8]) -> bool {
if data.len() < 8 { return false; }
let block_length = u16::from_be_bytes([data[0], data[1]]) as usize;
let mut off = 8 + block_length;
for _ in 0..6 {
let Some(&len) = data.get(off) else { return false };
off += 1 + len as usize;
}
off <= data.len()
} Type guard
fn intact_var_section<'a>(data: &'a [u8]) -> Option<&'a [u8]> {
var_fields_intact(data).then_some(data)
} Try / catch
match decode_execution_report(&frame) {
Ok(r) => handle(r),
Err(e) if e.to_string().contains("Buffer too short") => {
log::debug!("dropping truncated frame ({} bytes)", frame.len());
}
Err(e) => log::warn!("SBE decode failed: {e}"),
} Prevention
- Verify end-to-end frame length accounting before decode
- Use checksums or length prefixes when storing/replaying captures
- Avoid slicing captures at arbitrary byte offsets
- Fail loudly on truncation so transport bugs surface in testing
When it happens
Trigger: Calling decode_execution_report with a frame whose trailing variable-length section is cut mid-field — e.g. a symbol advertised as 6 bytes but only 3 present; truncated network message or truncated capture.
Common situations: Network/truncation issues splitting SBE frames; binary fixtures clipped at a byte boundary; corruption when persisting or replaying captured messages.
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
- SBE execution report block length too short: expected at lea
- Buffer too short for fixed block: expected {min_len}, was {}
- Buffer too short for {field} length: expected {}, was {}
- Symbol '{}' is not trading (status: {})
- Buffer too short for SBE header: expected {HEADER_LEN}, was
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/756be37e21cbf040.
Report an issue: GitHub.