{"record":{"id":"210fc456416f5f75","repo":"nautechsystems/nautilus_trader","slug":"failed-to-parse-acc-fill-sz-acc-fill-sz-e","errorCode":null,"errorMessage":"Failed to parse acc_fill_sz='{acc_fill_sz}': {e}","messagePattern":"Failed to parse acc_fill_sz='(.+?)': (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/websocket/parse.rs","lineNumber":2112,"sourceCode":"        anyhow::anyhow!(\n            \"Failed to parse price (fill_px='{}', avg_px='{}', px='{}'): {}\",\n            msg.fill_px,\n            msg.avg_px,\n            msg.px,\n            e\n        )\n    })?;\n\n    // OKX provides fillSz (incremental fill) or accFillSz (cumulative total)\n    // If fillSz is provided, use it directly as the incremental fill quantity\n    let last_qty = if !msg.fill_sz.is_empty() && msg.fill_sz != \"0\" {\n        parse_quantity(&msg.fill_sz, size_precision)\n            .map_err(|e| anyhow::anyhow!(\"Failed to parse fill_sz='{}': {e}\", msg.fill_sz,))?\n    } else if let Some(ref acc_fill_sz) = msg.acc_fill_sz {\n        // If fillSz is missing but accFillSz is available, calculate incremental fill\n        if !acc_fill_sz.is_empty() && acc_fill_sz != \"0\" {\n            let current_filled = parse_quantity(acc_fill_sz, size_precision).map_err(|e| {\n                anyhow::anyhow!(\"Failed to parse acc_fill_sz='{acc_fill_sz}': {e}\",)\n            })?;\n\n            // Calculate incremental fill as: current_total - previous_total\n            if let Some(prev_qty) = previous_filled_qty {\n                if current_filled < prev_qty {\n                    anyhow::bail!(\n                        \"Cumulative fill went backwards: acc_fill_sz='{acc_fill_sz}' < previous_filled_qty={prev_qty} \\\n                         (possible stale data after reconnect)\"\n                    );\n                }\n                let incremental = current_filled - prev_qty;\n                if incremental.is_zero() {\n                    log::debug!(\n                        \"Skipping duplicate fill: acc_fill_sz='{acc_fill_sz}' unchanged from previous={prev_qty}\"\n                    );\n                    return Ok(None);\n                }\n                incremental","sourceCodeStart":2094,"sourceCodeEnd":2130,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/websocket/parse.rs#L2094-L2130","documentation":"When fillSz is absent, the adapter derives the incremental fill from the cumulative accFillSz. This error is thrown when parse_quantity fails on acc_fill_sz, meaning the cumulative filled total cannot be represented at the instrument's size precision and the incremental fill cannot be computed.","triggerScenarios":"parse_fill_report gets an order update where fill_sz is empty/\"0\", acc_fill_sz (Option) is Some and non-empty/!=\"0\", but parse_quantity(acc_fill_sz, size_precision) fails — non-numeric, negative, or finer precision than size_precision.","commonSituations":"Instrument definitions cached before an OKX lotSz change; accFillSz arriving with more decimals than the instrument allows; partially-filled order pushes on newly listed instruments with locally stale specs.","solutions":["Refresh instrument definitions so size_precision covers the accFillSz decimals.","Inspect the raw payload to confirm accFillSz is a valid non-negative number.","Resync order state via REST to recover from the bad update.","Patch the adapter's parse_quantity/model if OKX changed the format."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Rust: pre-validate accFillSz when fillSz is absent\nfn acc_fill_sz_ok(acc: &Option<String>, precision: u32) -> bool {\n    acc.as_deref().map_or(true, |s| s.is_empty() || s == \"0\"\n        || rust_decimal::Decimal::from_str(s).map(|d| d.is_sign_positive() && d.scale() as u32 <= precision).unwrap_or(false))\n}","typeGuard":null,"tryCatchPattern":"match parse_fill_report(&msg, ...) {\n    Ok(r) => emit(r),\n    Err(e) => { log::warn!(\"accFillSz parse failed: {e}\"); mark_order_dirty(&msg.inst_id); }\n}","preventionTips":["Refresh lotSz/size_precision before subscribing; stale specs are the top cause.","Verify newly listed instruments are re-fetched before trading them.","Compare REST fill history against stream fills to detect silent parse drops."],"tags":["parsing","okx","quantity","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"}