{"record":{"id":"821d5edbabdf599d","repo":"nautechsystems/nautilus_trader","slug":"wrong-template-id-expected-outbound-account-posi","errorCode":null,"errorMessage":"Wrong template ID: expected {outbound_account_position_event_codec::SBE_TEMPLATE_ID}, received {template_id}","messagePattern":"Wrong template ID: expected (.+?), received (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/spot/websocket/trading/decode_sbe.rs","lineNumber":262,"sourceCode":"///\n/// Returns error if the buffer is too short, the template ID is wrong,\n/// or the schema ID does not match.\npub fn decode_account_position(data: &[u8]) -> anyhow::Result<BinanceSpotAccountPositionMsg> {\n    if data.len() < HEADER_LEN {\n        anyhow::bail!(\n            \"Buffer too short for SBE header: expected {HEADER_LEN}, was {}\",\n            data.len()\n        );\n    }\n\n    let buf = ReadBuf::new(data);\n    let block_length = buf.get_u16_at(0);\n    let template_id = buf.get_u16_at(2);\n    let schema_id = buf.get_u16_at(4);\n    let version = buf.get_u16_at(6);\n\n    if template_id != outbound_account_position_event_codec::SBE_TEMPLATE_ID {\n        anyhow::bail!(\n            \"Wrong template ID: expected {}, received {template_id}\",\n            outbound_account_position_event_codec::SBE_TEMPLATE_ID\n        );\n    }\n\n    if schema_id != crate::spot::sbe::spot::SBE_SCHEMA_ID {\n        anyhow::bail!(\n            \"Wrong schema ID: expected {}, received {schema_id}\",\n            crate::spot::sbe::spot::SBE_SCHEMA_ID\n        );\n    }\n\n    let min_len = HEADER_LEN + block_length as usize;\n    if data.len() < min_len {\n        anyhow::bail!(\n            \"Buffer too short for fixed block: expected {min_len}, was {}\",\n            data.len()\n        );","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/spot/websocket/trading/decode_sbe.rs#L244-L280","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nlet pos = decode_account_position(frame)?; // frame is an execution report\n// after\nlet template_id = u16::from_be_bytes([frame[2], frame[3]]);\nlet pos = if template_id == outbound_account_position_event_codec::SBE_TEMPLATE_ID {\n    decode_account_position(frame)?\n} else {\n    return Err(anyhow::format_err!(\"not an account position frame\"));\n};","handlingStrategy":"validation","validationCode":"pub fn is_account_position_frame(data: &[u8]) -> bool {\n    data.len() >= 8\n        && u16::from_be_bytes([data[2], data[3]])\n            == outbound_account_position_event_codec::SBE_TEMPLATE_ID\n}","typeGuard":"fn as_account_position<'a>(data: &'a [u8]) -> Option<&'a [u8]> {\n    (data.len() >= 8\n        && u16::from_be_bytes([data[2], data[3]])\n            == outbound_account_position_event_codec::SBE_TEMPLATE_ID)\n    .then_some(data)\n}","tryCatchPattern":"match decode_account_position(&frame) {\n    Ok(p) => handle(p),\n    Err(e) if e.to_string().contains(\"Wrong template ID\") => dispatch_by_template(&frame),\n    Err(e) => log::warn!(\"SBE decode failed: {e}\"),\n}","preventionTips":["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"],"tags":["sbe","binance","websocket","decoding"],"backgroundTag":"schema-validation-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}