nautechsystems/nautilus_trader · error · anyhow::Error

`{PRICE_PRECISION_PARAM}` must be less than or equal to {u8:

Error message

`{PRICE_PRECISION_PARAM}` must be less than or equal to {u8::MAX}

What it means

Databento subscription parameters may carry a price precision override via the `PRICE_PRECISION_PARAM` metadata key. Because the adapter stores precision as u8, any value larger than 255 cannot be represented and triggers this error. The raw param is read as u64 then converted with try_from.

Source

Thrown at crates/adapters/databento/src/data.rs:1404

fn requested_instrument(
    instruments: Vec<InstrumentAny>,
    instrument_id: InstrumentId,
) -> Option<InstrumentAny> {
    instruments
        .into_iter()
        .rev()
        .find(|instrument| instrument.id() == instrument_id)
}

fn price_precision_from_params(params: Option<&Params>) -> anyhow::Result<Option<u8>> {
    let Some(price_precision) = params.and_then(|params| params.get_u64(PRICE_PRECISION_PARAM))
    else {
        return Ok(None);
    };

    Ok(Some(u8::try_from(price_precision).map_err(|_| {
        anyhow::anyhow!(
            "`{PRICE_PRECISION_PARAM}` must be less than or equal to {}",
            u8::MAX
        )
    })?))
}

fn schema_from_params(
    params: Option<&Params>,
    default_schema: dbn::Schema,
    allowed_schemas: &[dbn::Schema],
) -> anyhow::Result<dbn::Schema> {
    let schema = if let Some(schema) = params.and_then(|params| params.get_str(SCHEMA_PARAM)) {
        dbn::Schema::from_str(schema)?
    } else {
        default_schema
    };

    if allowed_schemas.contains(&schema) {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass a price_precision value between 0 and 255
  2. Verify the param is an instrument precision count, not a scaled price
  3. Fix the config/code that computes the precision value (e.g. a double-scaling bug)
  4. Omit the parameter entirely to use the instrument's default precision

Example fix

// before
let params = indexmap! { PRICE_PRECISION_PARAM => 1000_u64.into() }; // > u8::MAX
// after
let params = indexmap! { PRICE_PRECISION_PARAM => 8_u64.into() };
Defensive patterns

Strategy: validation

Validate before calling

fn validate_precision_param(params: &dyn Params) -> Result<(), String> {
    match params.get_u64("price_precision") {
        Some(p) if p > u8::MAX as u64 => Err(format!("price_precision {p} exceeds u8::MAX")),
        _ => Ok(()),
    }
}

Type guard

fn valid_precision(v: u64) -> Option<u8> {
    u8::try_from(v).ok()
}

Try / catch

match result {
    Err(e) if e.to_string().contains("must be less than or equal to 255") => {
        eprintln!("price_precision param too large; use 0-255");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Passing a `price_precision` parameter greater than 255 (u8::MAX) to subscribe_quotes, subscribe_trades, request_quotes, request_trades, request_bars, or request_book_depth.

Common situations: Copy-pasting large precision values intended for other exchanges (crypto venues with 9-18 decimals are fine, but values like 1000 are invalid), or accidentally passing a price in raw fixed-point integer units instead of a precision count.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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