{"record":{"id":"3c1085e63c80db9e","repo":"nautechsystems/nautilus_trader","slug":"failed-to-parse-spread-acc-fill-sz-e","errorCode":null,"errorMessage":"Failed to parse spread acc_fill_sz='{}': {e}","messagePattern":"Failed to parse spread acc_fill_sz='(.+?)': (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/websocket/parse.rs","lineNumber":2011,"sourceCode":"\n    Ok(report)\n}\n\nfn parse_spread_order_fill_report(\n    msg: &OKXSpreadOrder,\n    instrument: &InstrumentAny,\n    _account_id: AccountId,\n    previous_filled_qty: Option<Quantity>,\n    _ts_init: UnixNanos,\n) -> anyhow::Result<Option<FillReport>> {\n    let size_precision = instrument.size_precision();\n    if !msg.fill_sz.is_empty() && msg.fill_sz != \"0\" {\n        parse_quantity(&msg.fill_sz, size_precision).map_err(|e| {\n            anyhow::anyhow!(\"Failed to parse spread fill_sz='{}': {e}\", msg.fill_sz)\n        })?;\n    } else if !msg.acc_fill_sz.is_empty() && msg.acc_fill_sz != \"0\" {\n        let current_filled = parse_quantity(&msg.acc_fill_sz, size_precision).map_err(|e| {\n            anyhow::anyhow!(\n                \"Failed to parse spread acc_fill_sz='{}': {e}\",\n                msg.acc_fill_sz\n            )\n        })?;\n\n        if let Some(prev_qty) = previous_filled_qty {\n            if current_filled < prev_qty {\n                anyhow::bail!(\n                    \"Cumulative spread fill went backwards: acc_fill_sz='{}' < previous_filled_qty={} \\\n                     (possible stale data after reconnect)\",\n                    msg.acc_fill_sz,\n                    prev_qty\n                );\n            }\n\n            if (current_filled - prev_qty).is_zero() {\n                log::debug!(\n                    \"Skipping duplicate spread fill: acc_fill_sz='{}' unchanged from previous={}\",","sourceCodeStart":1993,"sourceCodeEnd":2029,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/websocket/parse.rs#L1993-L2029","documentation":"When a spread order message has no incremental fill_sz, the adapter falls back to parsing the cumulative filled size acc_fill_sz with the spread instrument's size precision. This error is thrown when that cumulative value cannot be converted to a Quantity, so no incremental fill can be derived and the fill report must be aborted.","triggerScenarios":"parse_spread_order_event / parse_spread_order_msg get a spread order update where fill_sz is empty or \"0\" and acc_fill_sz is non-empty and not \"0\", but parse_quantity(acc_fill_sz, size_precision) fails (non-numeric text, negative value, more decimals than size_precision).","commonSituations":"Exchange sends accFillSz with precision exceeding the locally cached spread instrument's lotSz; a stale instrument definition after OKX changed spread tick/lot sizes; unexpected payload from an undocumented spread channel change.","solutions":["Refresh the spread instrument definition so size_precision accommodates the received acc_fill_sz precision.","Inspect the raw message payload to confirm acc_fill_sz is numeric and non-negative.","Resynchronize order/fill state from REST if the WebSocket stream delivered bad or stale data.","Update the adapter's parsing/model code if OKX changed the accFillSz format."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Rust: check acc_fill_sz parses cleanly before processing the update\nfn is_valid_acc_fill_sz(acc: &str, precision: u32) -> bool {\n    rust_decimal::Decimal::from_str(acc).map(|d| d.is_sign_positive() && d.scale() as u32 <= precision).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match parse_spread_order_event(msg, instrument, ...) {\n    Ok(v) => handle(v),\n    Err(e) => { log::warn!(\"spread acc_fill_sz error: {e:#}\"); schedule_rest_resync(); }\n}","preventionTips":["Keep cached spread instrument specs in sync with OKX's instruments endpoint.","Alert on parse failures per instrument to catch stale lotSz quickly.","Prefer adapters/branches matching your OKX API version."],"tags":["parsing","websocket","okx","order-fill"],"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-14T05:17:10.506Z"}