{"record":{"id":"45cd78d7de08652b","repo":"nautechsystems/nautilus_trader","slug":"failed-to-parse-fallback-quantity-for-ord-id-s","errorCode":null,"errorMessage":"Failed to parse fallback quantity for ord_id={}, sz='{}': {e}","messagePattern":"Failed to parse fallback quantity for ord_id=(.+?), sz='(.+?)': (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/common/parse.rs","lineNumber":761,"sourceCode":"            log::warn!(\n                \"No price available for conversion: ord_id={}, px='{}', avg_px='{}'\",\n                order.ord_id.as_str(),\n                order.px,\n                order.avg_px\n            );\n            None\n        };\n\n        // Convert quote quantity to base: quantity_base = sz_quote / price\n        let quantity_base = if let (Some(sz), Some(price)) = (sz_quote_dec, conversion_price_dec) {\n            if price.is_zero() {\n                log::warn!(\n                    \"Cannot convert quote quantity with zero price: ord_id={}, sz={}, using sz as-is\",\n                    order.ord_id.as_str(),\n                    order.sz\n                );\n                Quantity::from_str(&order.sz).map_err(|e| {\n                    anyhow::anyhow!(\n                        \"Failed to parse fallback quantity for ord_id={}, sz='{}': {e}\",\n                        order.ord_id.as_str(),\n                        order.sz\n                    )\n                })?\n            } else {\n                let quantity_dec = sz / price;\n                Quantity::from_decimal_dp(quantity_dec, size_precision).map_err(|e| {\n                    anyhow::anyhow!(\n                        \"Failed to convert quote-to-base quantity for ord_id={}, sz={sz}, price={price}, quantity_dec={quantity_dec}: {e}\",\n                        order.ord_id.as_str()\n                    )\n                })?\n            }\n        } else {\n            log::warn!(\n                \"Cannot convert quote quantity to base without price, using raw sz: \\\n                 ord_id={}, sz={}, px='{}', avg_px='{}'\",","sourceCodeStart":743,"sourceCodeEnd":779,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/common/parse.rs#L743-L779","documentation":"In parse_order_status_report, when a quote-currency order has a zero conversion price, the parser falls back to using the raw sz string as the base quantity. If that string cannot be parsed into a Quantity, this error is raised. It means OKX returned an sz value that is not a valid decimal number.","triggerScenarios":"A quote-quantity order (tgt_ccy=QuoteCcy, or spot/margin BUY market order per the heuristic) where px and avg_px are empty/zero, AND order.sz contains a non-numeric, empty, or malformed string (e.g. \"\", \"1,000\", scientific notation out of range).","commonSituations":"Cancelled or unfilled market orders with no price yet; OKX returning empty strings for fields on cancelled orders; locale-formatted numbers copied in custom responses; new OKX API versions changing field formats.","solutions":["Log order.sz, order.px and order.avg_px for the failing ord_id to see the raw payload","Check the OKX order record for empty/placeholder sz and skip such orders before parsing","Upgrade the nautilus OKX adapter so empty/zero-price quote orders are handled upstream","If sz uses an unexpected format, file an issue with the raw response and handle the format in a preprocessing step"],"exampleFix":"// before\nlet report = parse_order_status_report(&order, ...)?;\n// after\nif order.sz.trim().is_empty() {\n    log::warn!(\"Skipping order {} with empty sz\", order.ord_id);\n    return Ok(None);\n}\nlet report = parse_order_status_report(&order, ...)?;","handlingStrategy":"validation","validationCode":"fn is_valid_decimal_string(s: &str) -> bool { !s.trim().is_empty() && rust_decimal::Decimal::from_str(s.trim()).is_ok() }\n// call before: if !is_valid_decimal_string(&order.sz) { skip }","typeGuard":"fn parseable_quantity(s: &str) -> Option<Quantity> { Quantity::from_str(s).ok() }","tryCatchPattern":"match parse_order_status_report(&order, &instrument, ts_init) {\n    Ok(r) => handle(r),\n    Err(e) if e.to_string().contains(\"fallback quantity\") => log::warn!(\"unparseable sz for {}: {e}\", order.ord_id),\n    Err(e) => return Err(e),\n}","preventionTips":["Pre-validate numeric string fields from OKX payloads","Skip cancelled/empty orders before parsing","Keep instrument definitions in sync with OKX lotSz/tickSz","Add fixture tests covering empty-field edge cases"],"tags":["okx","rust","parsing","quantity","decimal"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}