nautechsystems/nautilus_trader · error
Failed to create quantity from {quantity_dec}: {e}
Error message
Failed to create quantity from {quantity_dec}: {e} What it means
parse_spot_margin_position_from_balance converts the OKX spot-in-use balance into a Nautilus quantity. Quantity::from_decimal_dp fails when the spotInUseAmt decimal cannot be represented at the instrument's size precision (wrong precision or malformed value), and the error is wrapped with the quantity value.
Source
Thrown at crates/adapters/okx/src/common/parse.rs:999
}
// Check if spotInUseAmt is zero first
if spot_in_use_dec.is_zero() {
// No position if spotInUseAmt is zero (regardless of liability)
return Ok(None);
}
// Position side based on spotInUseAmt sign
let (position_side, quantity_dec) = if spot_in_use_dec.is_sign_negative() {
// Negative spotInUseAmt = sold (short position)
(PositionSide::Short, spot_in_use_dec.abs())
} else {
// Positive spotInUseAmt = bought (long position)
(PositionSide::Long, spot_in_use_dec)
};
let quantity = Quantity::from_decimal_dp(quantity_dec, size_precision)
.map_err(|e| anyhow::anyhow!("Failed to create quantity from {quantity_dec}: {e}"))?;
let ts_last = parse_millisecond_timestamp(balance.u_time);
Ok(Some(PositionStatusReport::new(
account_id,
instrument_id,
position_side,
quantity,
ts_last,
ts_init,
None, // report_id
None, // venue_position_id is None for net mode margin positions
None, // avg_px_open not available from balance
)))
}
/// Parses an OKX position into a Nautilus [`PositionStatusReport`].
///View on GitHub (pinned to 18893faf8b)
Solutions
- Check that size_precision passed to the function matches the instrument's size increment from the OKX instruments endpoint
- Log the raw spotInUseAmt and precision; verify the value has <= size_precision decimal places
- Re-fetch instrument definitions so precision metadata is current
- Round/normalize the quantity to size_precision before calling Quantity::from_decimal_dp
Example fix
// before
let quantity = Quantity::from_decimal_dp(quantity_dec, size_precision)
.map_err(|e| anyhow::anyhow!("Failed to create quantity from {quantity_dec}: {e}"))?;
// after
let quantity_dec = quantity_dec.round_dp(size_precision as u32);
let quantity = Quantity::from_decimal_dp(quantity_dec, size_precision)
.map_err(|e| anyhow::anyhow!("Failed to create quantity from {quantity_dec}: {e}"))?; Defensive patterns
Strategy: validation
Validate before calling
// Rust: check precision fits before calling
fn quantity_fits_precision(dec: rust_decimal::Decimal, precision: u8) -> bool {
dec.round_dp(precision as u32) == dec
}
assert!(quantity_fits_precision(quantity_dec, size_precision), "quantity exceeds size precision"); Try / catch
match parse_spot_margin_position_from_balance(&balance, account_id, instrument_id, size_precision, ts_init) {
Ok(report) => report,
Err(e) => { tracing::error!("position quantity rejected: {e:#}"); return; }
} Prevention
- Always derive size_precision from the fetched OKX instrument definition, never hardcode
- Re-sync instrument metadata when OKX changes lot size rules
- Log raw balance payloads on parse failure for diagnosis
When it happens
Trigger: Calling parse_spot_margin_position_from_balance with an OKX balance-and-position payload whose spotInUseAmt has more decimal places than size_precision, or a non-representable value (e.g. scientific notation, negative, or a wrong precision passed by the caller).
Common situations: Instrument definitions loaded with an incorrect size_precision for the trading pair; stale instrument metadata after an OKX lot-size change; spot-margin liability amounts with unexpected precision from the account/balance endpoint.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unknown position currency '{pos_ccy}' for instrument {instru
- Invalid timeframe for `BarSpecification`, was {timeframe}
- missing fee
- Invalid funding_rate value: {e}
- Invalid funding_interval, cannot be negative
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b0ff56d00646c199.
Report an issue: GitHub.