{"record":{"id":"6f2b28efb43c0981","repo":"nautechsystems/nautilus_trader","slug":"empty-order-book-no-valid-price-levels-for-market","errorCode":null,"errorMessage":"Empty order book: no valid price levels for market order","messagePattern":"Empty order book: no valid price levels for market order","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/execution/parse.rs","lineNumber":774,"sourceCode":"    for level in book_levels {\n        let price = parse_decimal_exact(&level.price).context(\"invalid market-book price\")?;\n        let size = parse_decimal_exact(&level.size).context(\"invalid market-book size\")?;\n        anyhow::ensure!(\n            price > Decimal::ZERO && price < Decimal::ONE,\n            InvalidMarketPriceError(\"market-book price must be in (0, 1)\".to_string())\n        );\n        anyhow::ensure!(\n            size >= Decimal::ZERO,\n            \"market-book size must be non-negative\"\n        );\n\n        if !size.is_zero() {\n            parsed_levels.push((price, size));\n        }\n    }\n\n    if parsed_levels.is_empty() {\n        anyhow::bail!(\"Empty order book: no valid price levels for market order\");\n    }\n\n    match side {\n        PolymarketOrderSide::Buy => parsed_levels.sort_by_key(|a| a.0),\n        PolymarketOrderSide::Sell => parsed_levels.sort_by_key(|b| std::cmp::Reverse(b.0)),\n    }\n\n    let mut remaining = amount;\n    let mut last_price = Decimal::ZERO;\n    let mut total_base_qty = Decimal::ZERO;\n\n    for &(price, size) in &parsed_levels {\n        last_price = price;\n\n        match side {\n            PolymarketOrderSide::Buy => {\n                let level_usdc = size\n                    .checked_mul(price)","sourceCodeStart":756,"sourceCodeEnd":792,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/execution/parse.rs#L756-L792","documentation":"After parsing book levels, calculate_market_price drops levels with zero price or zero size; if nothing valid remains it bails out, since a book whose every level is degenerate offers no tradable price. This differs from the fully-empty-book case: levels were present but none were usable.","triggerScenarios":"Calling calculate_market_price with a non-empty book_levels slice where every level has price == 0 or size == 0 — typically from a malformed or placeholder API snapshot (all-zero payload) rather than a genuinely empty array.","commonSituations":"Upstream exchange returning zero-filled book rows during incidents; deserialization of a stub/placeholder book; stale cached snapshots zeroed out by a serializer bug.","solutions":["Filter or sanitize book levels before calling, and treat an all-degenerate book as 'no liquidity'.","Re-fetch the book from the CLOB API; an all-zero snapshot is usually transient or malformed.","Log the raw payload when this fires to confirm whether the adapter or the exchange produced the bad data.","Check adapter/API version compatibility in case the book schema changed and fields now deserialize as zero."],"exampleFix":"// before\nlet mp = calculate_market_price(&book.levels, amount, side)?;\n// after\nlet valid: Vec<_> = book.levels.iter().filter(|l| !l.size.is_zero() && !l.price.is_zero()).collect();\nanyhow::ensure!(!valid.is_empty(), \"book has no tradable levels; skipping\");\nlet mp = calculate_market_price(&book.levels, amount, side)?;","handlingStrategy":"validation","validationCode":"let usable = book_levels.iter()\n    .any(|l| !l.price.is_zero() && !l.size.is_zero());\nif !usable {\n    return Err(\"book contains only zero price/size levels\".into());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Sanitize or drop zero-sized/zero-priced levels before pricing","Log raw book payloads when all levels are degenerate","Pin the expected book schema in deserialization tests","Treat an all-zero book as no-liquidity, equivalent to an empty book"],"tags":["polymarket","order-book","data-quality","market-order"],"backgroundTag":"unexpected-api-response-shape","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"}