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
- Parse the header template ID and dispatch: 607→decode_account_position, 603→decode_execution_report, 601→balance update decoder
- Fix routing logic so account-position frames only reach this decoder
- Re-encode fixtures with outbound_account_position_event_codec
- 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
- Write one template-ID dispatcher for all user-data SBE frames
- Keep per-event test fixtures encoded with their own codec
- Don't infer event type from stream names alone; read the header
- Regenerate codecs if Binance revises template IDs
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
- Buffer too short for SBE header: expected {HEADER_LEN}, was
- Wrong template ID: expected {execution_report_event_codec::S
- Failed to advance balances group: {e:?}
- missing broker client order ID signal
- unknown broker client order ID signal byte '{}'
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/821d5edbabdf599d.
Report an issue: GitHub.