nautechsystems/nautilus_trader · error

`list_time` is required for {}

Error message

`list_time` is required for {}

What it means

parse_spread_instrument requires OKX spread definitions to carry a list_time (millisecond timestamp) to build the instrument activation time. If list_time is absent (None) the error '`list_time` is required for {sprd_id}' is raised.

Source

Thrown at crates/adapters/okx/src/common/parse.rs:1664

    }

    if definition.lot_sz.is_empty() {
        anyhow::bail!("`lot_sz` is empty for {}", definition.sprd_id);
    }

    let context = format!("SPREAD instrument {}", definition.sprd_id);
    let instrument_id = parse_instrument_id(definition.sprd_id);
    let raw_symbol = Symbol::from_ustr_unchecked(definition.sprd_id);
    let underlying =
        Currency::get_or_create_crypto_with_context(definition.base_ccy, Some(&context));
    let quote_currency =
        Currency::get_or_create_crypto_with_context(definition.quote_ccy, Some(&context));
    let settlement_currency = spread_settlement_currency(definition, underlying, quote_currency);
    let is_inverse = matches!(definition.sprd_type, OKXSpreadType::Inverse);
    let activation_ns = definition
        .list_time
        .map(parse_millisecond_timestamp)
        .ok_or_else(|| anyhow::anyhow!("`list_time` is required for {}", definition.sprd_id))?;
    let expiration_ns = definition
        .exp_time
        .map(parse_millisecond_timestamp)
        .unwrap_or_default();
    let ts_event = definition
        .u_time
        .map_or(ts_init, parse_millisecond_timestamp);

    let price_increment = Price::from_str(&definition.tick_sz).map_err(|e| {
        anyhow::anyhow!(
            "Failed to parse `tick_sz` '{}' for {}: {e}",
            definition.tick_sz,
            definition.sprd_id
        )
    })?;
    let size_increment = Quantity::from_str(&definition.lot_sz).map_err(|e| {
        anyhow::anyhow!(
            "Failed to parse `lot_sz` '{}' for {}: {e}",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Re-fetch the spread instrument definition from the OKX /sprd/instruments endpoint ensuring list_time is present
  2. Supply list_time (ms epoch) explicitly when constructing definitions from cached/manual data
  3. Check OKX API for changed availability of list_time for the spread type
  4. If list_time is genuinely optional upstream, relax to unwrap_or_default like exp_time

Example fix

// before
let activation_ns = definition
    .list_time
    .map(parse_millisecond_timestamp)
    .ok_or_else(|| anyhow::anyhow!("`list_time` is required for {}", definition.sprd_id))?;
// after
let activation_ns = definition
    .list_time
    .map_or(0, parse_millisecond_timestamp);
Defensive patterns

Strategy: validation

Validate before calling

fn spread_def_parsable(def: &OKXSpreadInstrument) -> bool {
    def.list_time.is_some() && !def.tick_sz.is_empty() && !def.lot_sz.is_empty()
}

Try / catch

match parse_spread_instrument(&definition, ts_init) {
    Ok(inst) => inst,
    Err(e) => { tracing::warn!("skipping spread {} def: {e:#}", definition.sprd_id); return Ok(None); }
}

Prevention

When it happens

Trigger: Calling parse_spread_instrument (via request_spread_instruments or request_spread_instrument) with a spread definition JSON that omits the list_time field.

Common situations: Manually constructed or trimmed fixtures missing list_time; newer OKX spread listings that don't populate list_time; caching definitions stripped of null/optional fields.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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