nautechsystems/nautilus_trader · error

Wrong template ID: expected {execution_report_event_codec::S

Error message

Wrong template ID: expected {execution_report_event_codec::SBE_TEMPLATE_ID}, received {template_id}

What it means

decode_execution_report validates the 8-byte SBE message header of a Binance Spot user-data binary frame before decoding. This error fires when the header's template ID is not the ExecutionReportEvent template (603), meaning the payload is a different SBE message type routed to the wrong decoder. The library bails early instead of misinterpreting bytes of another template as an execution report.

Source

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

///
/// 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
        );
    }

    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}"
        );
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the frame actually came from the executionReport user-data event before calling this decoder
  2. Parse the SBE header's template ID first and dispatch to the matching decoder (601→balance update, 603→execution report, 607→account position)
  3. Regenerate/update the codecs if Binance bumped the template ID in a schema revision
  4. Fix test fixtures to use a buffer encoded with the execution_report_event_codec

Example fix

// before
let report = decode_execution_report(raw_frame).unwrap();
// after
let template_id = u16::from_be_bytes([raw_frame[2], raw_frame[3]]);
let report = match template_id {
    execution_report_event_codec::SBE_TEMPLATE_ID => decode_execution_report(raw_frame)?,
    _ => return Err(anyhow::format_err!("unexpected template {template_id}")),
};
Defensive patterns

Strategy: validation

Validate before calling

pub fn is_execution_report_frame(data: &[u8]) -> bool {
    data.len() >= 8
        && u16::from_be_bytes([data[2], data[3]]) == execution_report_event_codec::SBE_TEMPLATE_ID
}

Type guard

fn as_execution_report(data: &[u8]) -> Option<&[u8]> {
    (data.len() >= 8
        && u16::from_be_bytes([data[2], data[3]]) == execution_report_event_codec::SBE_TEMPLATE_ID)
    .then_some(data)
}

Try / catch

match decode_execution_report(&frame) {
    Ok(report) => handle(report),
    Err(e) if e.to_string().contains("Wrong template ID") => route_to_other_decoder(&frame),
    Err(e) => log::warn!("SBE decode failed: {e}"),
}

Prevention

When it happens

Trigger: Calling decode_execution_report with a binary payload whose SBE header (bytes 2-3) carries a template ID other than 603 — e.g. a BalanceUpdateEvent (601) or OutboundAccountPositionEvent (607) frame, an out-of-order/duplicated stream event, or a hand-built test buffer with the wrong template.

Common situations: Routing frames by stream name instead of parsing the template ID before dispatch; Binance changing or the user mis-mapping user-data event types; writing unit tests that reuse a captured buffer from a different event type.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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