nautechsystems/nautilus_trader · error

Invalid `MboMsg` parsing combination

Error message

Invalid `MboMsg` parsing combination

What it means

For `MboMsg` records, `decode_record` expects the decoded result to be exactly one of: a book delta, a trade, or nothing. Any other combination (e.g. both a delta and a trade produced simultaneously) indicates an internal decoding invariant violation and is rejected.

Source

Thrown at crates/adapters/databento/src/decode/market_data.rs:801

    ts_init: Option<UnixNanos>,
    include_trades: bool,
    bars_timestamp_on_close: bool,
) -> anyhow::Result<(Option<Data>, Option<Data>)> {
    let result = if let Some(msg) = record.get::<dbn::MboMsg>() {
        let ts_init = determine_timestamp(ts_init, msg.ts_recv.into());
        let result = decode_mbo_msg(
            msg,
            instrument_id,
            price_precision,
            Some(ts_init),
            include_trades,
        )?;

        match result {
            (Some(delta), None) => (Some(Data::BookDelta(delta)), None),
            (None, Some(trade)) => (Some(Data::Trade(trade)), None),
            (None, None) => (None, None),
            _ => anyhow::bail!("Invalid `MboMsg` parsing combination"),
        }
    } else if let Some(msg) = record.get::<dbn::TradeMsg>() {
        let ts_init = determine_timestamp(ts_init, msg.ts_recv.into());
        let trade = decode_trade_msg(msg, instrument_id, price_precision, Some(ts_init))?;
        (Some(Data::Trade(trade)), None)
    } else if let Some(msg) = record.get::<dbn::Mbp1Msg>() {
        let ts_init = determine_timestamp(ts_init, msg.ts_recv.into());
        let (maybe_quote, maybe_trade) = decode_mbp1_msg(
            msg,
            instrument_id,
            price_precision,
            Some(ts_init),
            include_trades,
        )?;
        (maybe_quote.map(Data::Quote), maybe_trade.map(Data::Trade))
    } else if let Some(msg) = record.get::<dbn::Bbo1SMsg>() {
        let ts_init = determine_timestamp(ts_init, msg.ts_recv.into());
        let maybe_quote = decode_bbo_msg(msg, instrument_id, price_precision, Some(ts_init))?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the decoder version and upgrade — this usually indicates a library bug
  2. Capture the offending record (rtype, action, fields) and file a bug with the adapter maintainers
  3. Verify no local modifications changed `decode_mbo_msg` return semantics
Defensive patterns

Strategy: try-catch

Try / catch

match decode_record(record) {
    Ok(data) => data,
    Err(e) if e.to_string().contains("Invalid `MboMsg` parsing combination") => {
        log::error!("decoder invariant violated; capture record and report bug");
        None // skip record
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Decoding an MBO record (rtype 0 family / TCBBO paths) where the MBO decoder returns both `Some(delta)` and `Some(trade)` at once — a bug or unhandled case in `decode_mbo_msg` rather than bad user input.

Common situations: Running against new Databento record contents that exercise an untested MBO decode branch; custom builds where decode functions were modified; generally a decoder bug report scenario.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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