{"record":{"id":"d4a7e7d43a005b06","repo":"nautechsystems/nautilus_trader","slug":"wrong-template-id-expected-balance-update-event","errorCode":null,"errorMessage":"Wrong template ID: expected {balance_update_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":343,"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_balance_update(data: &[u8]) -> anyhow::Result<BinanceSpotBalanceUpdateMsg> {\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 != balance_update_event_codec::SBE_TEMPLATE_ID {\n        anyhow::bail!(\n            \"Wrong template ID: expected {}, received {template_id}\",\n            balance_update_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":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/spot/websocket/trading/decode_sbe.rs#L325-L361","documentation":"After parsing the SBE header, decode_balance_update validates the template ID field against balance_update_event_codec::SBE_TEMPLATE_ID. The template ID identifies which SBE message the payload encodes; a mismatch means the bytes are a different SBE message than a balance update. The library bails rather than misinterpreting another message type.","triggerScenarios":"Passing an SBE payload whose template ID differs from the balance-update template, e.g. an execution report, order update, or other event routed to decode_balance_update by mistake.","commonSituations":"A websocket message-dispatch switch that routes by stream name but receives a different message on that stream; Binance changing template IDs in a schema update; feeding one decoder the output intended for another event type.","solutions":["Verify the dispatch/multiplexing logic routes only balance-update events to this decoder","Log the received template_id and compare against balance_update_event_codec::SBE_TEMPLATE_ID","Regenerate/check the SBE codecs if Binance schema versions changed","Decode with a generic SBE header read first to identify the message type, then dispatch"],"exampleFix":"// before\nlet msg = decode_balance_update(&payload)?;\n// after\nlet template_id = u16::from_be_bytes([payload[2], payload[3]]);\nif template_id != balance_update_event_codec::SBE_TEMPLATE_ID {\n    tracing::debug!(template_id, \"not a balance update\");\n    return Ok(None);\n}\nlet msg = decode_balance_update(&payload)?;","handlingStrategy":"validation","validationCode":"let is_balance_update = payload.len() >= 4\n    && u16::from_be_bytes([payload[2], payload[3]]) == balance_update_event_codec::SBE_TEMPLATE_ID;","typeGuard":"fn is_balance_update_frame(data: &[u8]) -> bool {\n    data.len() >= 4\n        && u16::from_be_bytes([data[2], data[3]]) == balance_update_event_codec::SBE_TEMPLATE_ID\n}","tryCatchPattern":"match decode_balance_update(&payload) {\n    Ok(msg) => handle_balance(msg),\n    Err(e) if e.to_string().starts_with(\"Wrong template ID\") => {\n        log::debug!(\"wrong template, dispatching to other decoder\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Read the SBE template ID generically before dispatching to a specific decoder","Keep codecs regenerated in sync with Binance schema releases","Unit-test the stream multiplexer with mixed event types"],"tags":["rust","sbe","decoding","template-id"],"backgroundTag":"invalid-enum-value","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"}