{"record":{"id":"000147a13a38d111","repo":"nautechsystems/nautilus_trader","slug":"cannot-determine-fill-quantity-fill-sz-and-a","errorCode":null,"errorMessage":"Cannot determine fill quantity: fill_sz='{}' and acc_fill_sz is None","messagePattern":"Cannot determine fill quantity: fill_sz='(.+?)' and acc_fill_sz is None","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/websocket/parse.rs","lineNumber":2141,"sourceCode":"                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\n            } else {\n                // First fill, use accumulated as incremental\n                current_filled\n            }\n        } else {\n            anyhow::bail!(\n                \"Cannot determine fill quantity: fill_sz is empty/zero and acc_fill_sz is empty/zero\"\n            );\n        }\n    } else {\n        anyhow::bail!(\n            \"Cannot determine fill quantity: fill_sz='{}' and acc_fill_sz is None\",\n            msg.fill_sz\n        );\n    };\n\n    let fee_str = msg\n        .fee\n        .as_deref()\n        .filter(|fee| !fee.trim().is_empty())\n        .ok_or_else(|| anyhow::anyhow!(\"missing fee for fill report inst_id={}\", msg.inst_id))?;\n    let fee_dec = Decimal::from_str(fee_str)\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse fee '{fee_str}': {e}\"))?;\n\n    let fee_currency = parse_fee_currency(msg.fee_ccy.as_str(), fee_dec, || {\n        format!(\"fill report for inst_id={}\", msg.inst_id)\n    });\n\n    // OKX sends fees as negative numbers (e.g., \"-2.5\" for a $2.5 charge), parse_fee negates to positive","sourceCodeStart":2123,"sourceCodeEnd":2159,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/websocket/parse.rs#L2123-L2159","documentation":"This variant fires when fill_sz has a value but acc_fill_sz is None. OKX normally sends both on fills; acc_fill_sz alone lets the parser use the cumulative total, and fill_sz alone is insufficient because the parser can't validate monotonicity against previous fills.","triggerScenarios":"An orders-channel update carrying fill_sz but omitting acc_fill_sz entirely — typically an OKX API shape change, a different channel variant, or a hand-built message.","commonSituations":"OKX API version updates changing required fields; proxying messages through an intermediary that strips fields; incomplete test fixtures.","solutions":["Verify the OKX orders channel payload includes acc_fill_sz and update any message-model/serde definitions that drop it","If only incremental fill_sz is available, fall back to using fill_sz directly as the incremental quantity","Check for field-name/serde renames (camelCase vs snake_case) after upgrading the adapter"],"exampleFix":"// before\nstruct OKXOrderMsg { fill_sz: Option<String> } // acc_fill_sz dropped\n// after\nstruct OKXOrderMsg { fill_sz: Option<String>, acc_fill_sz: Option<String> }","handlingStrategy":"type-guard","validationCode":"if msg.acc_fill_sz.is_none() {\n    tracing::warn!(\"orders update missing acc_fill_sz; check API schema\");\n    return Ok(None);\n}","typeGuard":"fn has_cumulative_fill(msg: &OKXOrderMsg) -> bool { msg.acc_fill_sz.is_some() }","tryCatchPattern":"if !has_cumulative_fill(&msg) { /* fallback: use fill_sz incrementally or skip */ }","preventionTips":["Verify serde field mappings (acc_fill_sz) after adapter/API upgrades","Keep OKX message models updated against current API docs","Never strip fields when proxying OKX payloads through intermediaries"],"tags":["okx","parsing","websocket","missing-field"],"backgroundTag":"missing-required-argument","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"}