nautechsystems/nautilus_trader · error

Wrong template ID: expected {outbound_account_position_event

Error message

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

What it means

decode_account_position checks the SBE header's template ID against the OutboundAccountPositionEvent template (607). This error means the frame is a different SBE message type (e.g. ExecutionReportEvent 603 or BalanceUpdateEvent 601) that was routed to the account-position decoder. Bailing prevents decoding bytes under the wrong field layout.

Source

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

///
/// Returns error if the buffer is too short, the template ID is wrong,
/// or the schema ID does not match.
pub fn decode_account_position(data: &[u8]) -> anyhow::Result<BinanceSpotAccountPositionMsg> {
    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 != outbound_account_position_event_codec::SBE_TEMPLATE_ID {
        anyhow::bail!(
            "Wrong template ID: expected {}, received {template_id}",
            outbound_account_position_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_len = HEADER_LEN + block_length as usize;
    if data.len() < min_len {
        anyhow::bail!(
            "Buffer too short for fixed block: expected {min_len}, was {}",
            data.len()
        );

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Parse the header template ID and dispatch: 607→decode_account_position, 603→decode_execution_report, 601→balance update decoder
  2. Fix routing logic so account-position frames only reach this decoder
  3. Re-encode fixtures with outbound_account_position_event_codec
  4. If Binance changed the template ID, regenerate the codecs

Example fix

// before
let pos = decode_account_position(frame)?; // frame is an execution report
// after
let template_id = u16::from_be_bytes([frame[2], frame[3]]);
let pos = if template_id == outbound_account_position_event_codec::SBE_TEMPLATE_ID {
    decode_account_position(frame)?
} else {
    return Err(anyhow::format_err!("not an account position frame"));
};
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Calling decode_account_position on a frame whose header bytes 2-3 are not 607 — misrouted user-data events, dispatch keyed on stream/event names instead of the parsed template ID, or fixtures built with the wrong codec (see test_decode_account_position_wrong_template).

Common situations: Event dispatch tables mapping the wrong event to the wrong decoder; Binance sending an unexpected event on the user-data stream; copy-pasted test code reusing another event's encoded buffer.

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/821d5edbabdf599d. Report an issue: GitHub.