nautechsystems/nautilus_trader · error

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

Error message

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

What it means

Inside `get_range_quotes`, each decoded record is mapped to `Data::Quote(quote)` or `None` (undefined bid/ask, skipped). Any other `Data` variant means the schema produced a record type that is not a quote tick, which is an invariant violation for this method, so it errors with the debug representation of the offending element.

Source

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

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

            let (data, _) = decode_record(
                &record,
                instrument_id,
                price_precision,
                None,
                false, // Don't include trades
                true,
            )?;

            match data {
                Some(Data::Quote(quote)) => result.push(quote),
                None => {} // Skip records with undefined bid/ask prices
                _ => anyhow::bail!("Invalid data element not `QuoteTick`, was {data:?}"),
            }
            Ok(())
        };

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

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the printed `data:?` variant to see which record type leaked in; adjust the requested schema to one that yields only quotes.
  2. If the schema legitimately emits non-quote records, handle that variant explicitly instead of erroring.
  3. Upgrade/patch the adapter if this is a decode mismatch bug between schema handling and `Data` conversion.
  4. Filter records client-side: if you control record iteration, skip known non-quote record types before conversion.

Example fix

// before
_ => anyhow::bail!("Invalid data element not `QuoteTick`, was {data:?}"),
// after
_ => { log::debug!("skipping non-quote element {data:?}"); Ok(()) }
Defensive patterns

Strategy: try-catch

Type guard

fn is_quote(data: &Data) -> Option<&QuoteTick> { match data { Data::Quote(q) => Some(q), _ => None } }

Try / catch

match get_range_quotes(params).await {
    Ok(quotes) => quotes,
    Err(e) if e.to_string().contains("Invalid data element not `QuoteTick`") => {
        log::error!("non-quote record leaked: {e}"); Vec::new()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A record from a quote-capable schema decodes into a non-quote `Data` variant — e.g. cmbp-1/tcbbo streams yielding trade-implied records that map to a non-Quote variant, or an internal decode mismatch between the schema allow-list and `process_record`'s conversion.

Common situations: Mixed/multi-asset responses where some records are not quotes; adapter bug after a schema allow-list change; feeding cbbo/cmbp schemas whose records decode to trade ticks under certain conditions.

Related errors


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