nautechsystems/nautilus_trader · error · anyhow::Error
Failed to parse spread acc_fill_sz='{}': {e}
Error message
Failed to parse spread acc_fill_sz='{}': {e} What it means
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.
Source
Thrown at crates/adapters/okx/src/websocket/parse.rs:2011
Ok(report)
}
fn parse_spread_order_fill_report(
msg: &OKXSpreadOrder,
instrument: &InstrumentAny,
_account_id: AccountId,
previous_filled_qty: Option<Quantity>,
_ts_init: UnixNanos,
) -> anyhow::Result<Option<FillReport>> {
let size_precision = instrument.size_precision();
if !msg.fill_sz.is_empty() && msg.fill_sz != "0" {
parse_quantity(&msg.fill_sz, size_precision).map_err(|e| {
anyhow::anyhow!("Failed to parse spread fill_sz='{}': {e}", msg.fill_sz)
})?;
} else if !msg.acc_fill_sz.is_empty() && msg.acc_fill_sz != "0" {
let current_filled = parse_quantity(&msg.acc_fill_sz, size_precision).map_err(|e| {
anyhow::anyhow!(
"Failed to parse spread acc_fill_sz='{}': {e}",
msg.acc_fill_sz
)
})?;
if let Some(prev_qty) = previous_filled_qty {
if current_filled < prev_qty {
anyhow::bail!(
"Cumulative spread fill went backwards: acc_fill_sz='{}' < previous_filled_qty={} \
(possible stale data after reconnect)",
msg.acc_fill_sz,
prev_qty
);
}
if (current_filled - prev_qty).is_zero() {
log::debug!(
"Skipping duplicate spread fill: acc_fill_sz='{}' unchanged from previous={}",View on GitHub (pinned to 18893faf8b)
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.
Defensive patterns
Strategy: validation
Validate before calling
// Rust: check acc_fill_sz parses cleanly before processing the update
fn is_valid_acc_fill_sz(acc: &str, precision: u32) -> bool {
rust_decimal::Decimal::from_str(acc).map(|d| d.is_sign_positive() && d.scale() as u32 <= precision).unwrap_or(false)
} Try / catch
match parse_spread_order_event(msg, instrument, ...) {
Ok(v) => handle(v),
Err(e) => { log::warn!("spread acc_fill_sz error: {e:#}"); schedule_rest_resync(); }
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
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 spread fill_sz='{}': {e}
- Unsupported algo order type: {:?}
- Missing sz for algo order {}
- Cannot determine spread fill quantity: fill_sz='{}' and acc_
- Cannot determine fill quantity: fill_sz is empty/zero and ac
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/3c1085e63c80db9e.
Report an issue: GitHub.