nautechsystems/nautilus_trader · error

Invalid data element not `TradeTick`, was {data:?}

Error message

Invalid data element not `TradeTick`, was {data:?}

What it means

During Databento historical trade fetching, each decoded record must decode to a `Data::Trade` variant. This error is raised when a record decodes to `None` for the primary data but yields a second non-Trade element (data2), i.e. the `(None, Some(data))` arm in `get_range_trades`. The decoder produced data the trade-fetcher cannot interpret as a trade tick, so it aborts rather than silently dropping records.

Source

Thrown at crates/adapters/databento/src/historical.rs:713

                &record,
                &mut metadata_cache,
                &self.publisher_venue_map,
                &sym_map,
            )?;
            let price_precision = self.resolve_cached_price_precision(
                &instrument_id,
                price_precision_arg,
                &mut precision_cache,
            )?;

            let (data, data2) =
                decode_record(&record, instrument_id, price_precision, None, true, true)?;

            match (data, data2) {
                (Some(Data::Trade(trade)), _) | (_, Some(Data::Trade(trade))) => result.push(trade),
                (Some(_) | None, None) => {}
                (None, Some(data)) => {
                    anyhow::bail!("Invalid data element not `TradeTick`, was {data:?}")
                }
                (Some(data), Some(_)) => {
                    anyhow::bail!("Invalid data element not `TradeTick`, was {data:?}")
                }
            }
            Ok(())
        };

        match dbn_schema {
            dbn::Schema::Trades => {
                while let Some(msg) = decoder.decode_record::<dbn::TradeMsg>().await? {
                    process_record(dbn::RecordRef::from(msg))?;
                }
            }
            dbn::Schema::Mbp1 => {
                while let Some(msg) = decoder.decode_record::<dbn::Mbp1Msg>().await? {
                    process_record(dbn::RecordRef::from(msg))?;
                }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the requested DBN schema for this call is a trade schema (Trades / Tcbbo), not OHLCV or MBO.
  2. Check the symbol/dataset: ensure `get_range_trades` is only called for instruments that publish trade data.
  3. Inspect the decoded element in the `{data:?}` message to identify which record type is actually being produced.
  4. If data legitimately contains non-trade records, filter it before decoding or use the appropriate range method (e.g. get_range_bars).

Example fix

// before
let trades = client.get_range_trades(&params, ...)?;
// after — ensure schema is trades
params.schema = Some("trades"); // or "tbbo"/"cbbo" where supported
let trades = client.get_range_trades(&params, ...)?;
Defensive patterns

Strategy: validation

Validate before calling

// Before calling, ensure the request schema is a trade schema
assert!(matches!(params.schema.as_deref(), None | Some("trades") | Some("tbbo") | Some("cbbo")),
    "get_range_trades requires a trade schema, got {:?}", params.schema);

Prevention

When it happens

Trigger: Calling `get_range_trades` on a schema/request whose decoded records yield `data2` that is not a `Data::Trade` — e.g. a mismatched DBN schema producing records the decoder maps to a secondary non-trade element instead of `Data::Trade`.

Common situations: Requesting trades against a dataset/symbol whose underlying schema changed or was misinterpreted; decoding records from an unexpected Databento schema (e.g. MBO or OHLCV data reaching the trade pipeline); a Databento SDK version change altering record decoding.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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