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
- Re-fetch the spread instrument definition from the OKX /sprd/instruments endpoint ensuring list_time is present
- Supply list_time (ms epoch) explicitly when constructing definitions from cached/manual data
- Check OKX API for changed availability of list_time for the spread type
- 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
- Never strip null/optional fields when caching definitions
- Validate required fields (list_time, tick_sz, lot_sz) at cache-write time
- Keep fixture JSON complete when writing tests
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
- missing fee for spread fill report sprd_id={}; OKX sprd-orde
- instrument update lock poisoned
- option_summary_family_subs mutex poisoned
- Conditional order types must use OKXAlgoOrderType
- Invalid `OrderType` cannot be represented on OKX: {value:?}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/adc1f2f34364e675.
Report an issue: GitHub.