nautechsystems/nautilus_trader · error
Failed to parse position quantity '{}' for instrument {}: {e
Error message
Failed to parse position quantity '{}' for instrument {}: {e:?} What it means
parse_position_status_report parses the `pos` field of an OKX position response into a Decimal. If the string is empty or not a valid decimal number, the error is raised naming the position quantity and instrument.
Source
Thrown at crates/adapters/okx/src/common/parse.rs:1042
///
/// - **Long/Short mode** (`posSide="long"` or `"short"`): The `pos` field is always
/// positive regardless of side. Position side is determined from the `posSide` field.
/// Position IDs are suffixed with `-LONG` or `-SHORT` for uniqueness.
///
/// See: <https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-positions>
///
/// # Errors
///
/// Returns an error if any numeric fields cannot be parsed into their target types.
pub fn parse_position_status_report(
position: &OKXPosition,
account_id: AccountId,
instrument_id: InstrumentId,
size_precision: u8,
ts_init: UnixNanos,
) -> anyhow::Result<PositionStatusReport> {
let pos_dec = Decimal::from_str(&position.pos).map_err(|e| {
anyhow::anyhow!(
"Failed to parse position quantity '{}' for instrument {}: {e:?}",
position.pos,
instrument_id
)
})?;
// For SPOT/MARGIN: determine position side and quantity based on pos_ccy
// - If pos_ccy = base currency: LONG position, pos is in base currency
// - If pos_ccy = quote currency: SHORT position, pos is in quote currency (needs conversion)
// - If pos_ccy is empty: FLAT position (no position)
let (position_side, quantity_dec) = if position.inst_type == OKXInstrumentType::Spot
|| position.inst_type == OKXInstrumentType::Margin
{
// Extract base and quote currencies from instrument symbol
let (base_ccy, quote_ccy) = parse_base_quote_from_symbol(instrument_id.symbol.as_str())?;
let pos_ccy = position.pos_ccy.as_str();
View on GitHub (pinned to 18893faf8b)
Solutions
- Check position.pos is a non-empty valid decimal string before calling the parser
- Skip or zero-fill positions with empty pos values before parsing
- Re-fetch positions from the OKX positions endpoint to replace stale/corrupt records
- Add a test fixture matching the actual OKX payload shape
Example fix
// before
let report = parse_position_status_report(&position, account_id, instrument_id, precision, ts_init)?;
// after
if position.pos.is_empty() {
return Ok(PositionStatusReport::closed(account_id, instrument_id, ts_init));
}
let report = parse_position_status_report(&position, account_id, instrument_id, precision, ts_init)?; Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_position_qty(pos: &str) -> bool {
!pos.is_empty() && pos.parse::<rust_decimal::Decimal>().is_ok()
} Try / catch
match parse_position_status_report(&position, account_id, instrument_id, size_precision, ts_init) {
Ok(report) => reports.push(report),
Err(e) => tracing::warn!("skipping unparseable position for {instrument_id}: {e:#}"),
} Prevention
- Treat empty pos as a flat/closed position before parsing
- Validate fixtures against the live OKX positions payload schema
- Keep adapter and API versions aligned
When it happens
Trigger: Calling parse_position_status_report when position.pos is an empty string, contains formatting characters, or is otherwise not parseable by Decimal::from_str.
Common situations: Flat/closed positions where OKX returns an empty pos field; a change in the OKX positions API payload; feeding in a manually crafted or cached JSON record with missing fields.
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
- Failed to parse fallback quantity for ord_id={}, sz='{}': {e
- Failed to parse filled quantity for ord_id={}, acc_fill_sz='
- Failed to parse base quantity for ord_id={}, sz='{}': {e}
- Failed to parse liab '{liab_str}': {e}
- Failed to parse spotInUseAmt '{spot_in_use_str}': {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/45b9dccc35184ee6.
Report an issue: GitHub.