nautechsystems/nautilus_trader · error
Failed to parse `tick_sz` '{}' into Price for {}: {e}
Error message
Failed to parse `tick_sz` '{}' into Price for {}: {e} What it means
OKX instrument parsing calls `Price::from_str` on the exchange-reported `tick_sz` field, and it failed to parse into the NautilusTrader `Price` type. The library throws this when an instrument definition carries a tick size value that is present but not a valid decimal price string. Parsing fails hard instead of guessing, since a wrong price increment corrupts order pricing downstream.
Source
Thrown at crates/adapters/okx/src/common/parse.rs:1951
common: CommonInstrumentData,
margin_fees: MarginAndFees,
ts_init: UnixNanos,
) -> anyhow::Result<InstrumentAny>;
}
/// Extracts common fields shared across all instrument types.
fn parse_common_instrument_data(
definition: &OKXInstrument,
) -> anyhow::Result<CommonInstrumentData> {
let instrument_id = parse_instrument_id(definition.inst_id);
let raw_symbol = Symbol::from_ustr_unchecked(definition.inst_id);
if definition.tick_sz.is_empty() {
anyhow::bail!("`tick_sz` is empty for {}", definition.inst_id);
}
let price_increment = Price::from_str(&definition.tick_sz).map_err(|e| {
anyhow::anyhow!(
"Failed to parse `tick_sz` '{}' into Price for {}: {e}",
definition.tick_sz,
definition.inst_id,
)
})?;
if definition.lot_sz.is_empty() {
anyhow::bail!("`lot_sz` is empty for {}", definition.inst_id);
}
let size_increment = Quantity::from_str(&definition.lot_sz).map_err(|e| {
anyhow::anyhow!(
"Failed to parse `lot_sz` '{}' for {}: {e}",
definition.lot_sz,
definition.inst_id,
)
})?;
let lot_size = Some(size_increment);View on GitHub (pinned to 18893faf8b)
Solutions
- Log/inspect the raw definition.tick_sz for the failing inst_id and confirm it is a plain decimal string like "0.1".
- Verify the value against the live OKX /api/v5/public/instruments response for that instId.
- If it comes from a fixture or cache, correct or regenerate the fixture from a fresh OKX response.
- If parsing still fails for a valid decimal, check the Price::from_str precision limits and normalize the string (trim whitespace, strip units) before parsing.
Example fix
// before let price_increment = Price::from_str(&definition.tick_sz).map_err(|e| ...)?; // after let tick = definition.tick_sz.trim(); let price_increment = Price::from_str(tick).map_err(|e| ...)?;
Defensive patterns
Strategy: validation
Validate before calling
fn is_decimal(s: &str) -> bool {
let t = s.trim();
!t.is_empty() && t.parse::<f64>().is_ok() && !t.contains(['e', 'E'])
}
// guard: assert!(is_decimal(definition.tick_sz), "bad tick_sz: {}", definition.tick_sz); Type guard
fn valid_price_str(s: &str) -> Option<&str> {
let t = s.trim();
if !t.is_empty() && t.parse::<f64>().is_ok() { Some(t) } else { None }
} Try / catch
match parse_instrument_with_parser(&definition, ts_init) {
Ok(inst) => inst,
Err(e) if e.to_string().contains("tick_sz") => {
tracing::warn!(inst_id = %definition.inst_id, "skipping instrument with bad tick_sz: {e}");
continue;
}
Err(e) => return Err(e),
} Prevention
- Validate instrument fields (tick_sz, lot_sz, min_sz, max_mkt_sz) against a decimal-string check immediately after fetching from OKX.
- Always fetch fixtures from real /api/v5/public/instruments responses, never hand-write them.
- Trim whitespace from exchange strings before parsing.
- Reject scientific notation early; convert to plain decimal before calling the parser.
When it happens
Trigger: Calling parse_common_instrument_data (via parse_instrument_with_parser or parse_event_contract_instrument) with an OkxInstrumentDef whose tick_sz is non-empty but not decimal-parseable (e.g. contains scientific notation, units, spaces, or unusual characters from an API schema change).
Common situations: Mocked or hand-crafted instrument JSON in tests; a cached/stale instrument response whose schema changed; OKX introducing a new instrument family with an unexpected tick_sz encoding; manual transcription of tick_sz when building fixtures.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid contract type '{}' for {}: expected 'linear' or 'inv
- `settle_ccy` or `quote_ccy` is required for EVENTS instrumen
- Failed to parse `max_mkt_sz` '{}' for {}: {e}
- Invalid underlying '{}' for {}: expected format 'BASE-QUOTE'
- `exp_time` is required for {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/df1c838e31f820a2.
Report an issue: GitHub.