{"record":{"id":"da77dc89add8ae82","repo":"nautechsystems/nautilus_trader","slug":"provider-maker-order-side-provider-side-contr","errorCode":null,"errorMessage":"provider maker order {} side {provider_side} contradicts derived side {derived_side}","messagePattern":"provider maker order (.+?) side (.+?) contradicts derived side (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/execution/reconciliation.rs","lineNumber":193,"sourceCode":"        trade.trader_side,\n    );\n    Ok(true)\n}\n\nfn validate_maker_order_side(\n    trade: &PolymarketTradeReport,\n    maker_order: &PolymarketMakerOrder,\n) -> anyhow::Result<OrderSide> {\n    let derived_side = determine_order_side(\n        trade.trader_side,\n        trade.side,\n        trade.asset_id.as_str(),\n        maker_order.asset_id.as_str(),\n    );\n    let provider_side = maker_order\n        .side\n        .with_context(|| format!(\"REST maker order {} is missing side\", maker_order.order_id))?;\n    anyhow::ensure!(\n        OrderSide::from(provider_side) == derived_side,\n        \"provider maker order {} side {provider_side} contradicts derived side {derived_side}\",\n        maker_order.order_id,\n    );\n    Ok(derived_side)\n}\n\nfn checked_venue_order_id(value: &str, evidence: &str) -> anyhow::Result<VenueOrderId> {\n    VenueOrderId::new_checked(value)\n        .with_context(|| format!(\"{evidence} has invalid venue order ID {value:?}\"))\n}\n\nfn checked_trade_id(value: &str, evidence: &str) -> anyhow::Result<TradeId> {\n    TradeId::new_checked(value)\n        .with_context(|| format!(\"{evidence} has invalid trade ID {value:?}\"))\n}\n\n#[derive(Clone, Copy)]","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/execution/reconciliation.rs#L175-L211","documentation":"When deriving an order's side from a fill/trade, the code validates the side reported by the provider REST endpoint for the maker order. This ensure! fires when OrderSide::from(provider REST side) differs from the side derived from the trade data, so the two sources of truth disagree.","triggerScenarios":"classify_target_trade or build_fill_reports_from_trades -> validate_maker_order_side fetches the maker order via REST; its side field (e.g. BUY/SELL) maps to a different OrderSide than the one derived from the trade's asset/role data.","commonSituations":"Polymarket REST and data-api endpoints disagreeing (one reporting the order side, the other the counter-side); parsing BUY/SELL enums case- or semantically-differently; stale cached REST order vs fresh trade.","solutions":["Print both values and check how OrderSide::from maps the provider side string; verify the mapping matches Polymarket's BUY/SELL semantics.","Re-fetch the maker order from REST to rule out staleness.","Check whether the derived side logic uses the correct perspective (own order vs counterparty) in the trade payload.","Update the side mapping or reconciliation logic after confirming which source is authoritative."],"exampleFix":"// before\nlet derived = derive_side_from_trade(trade);\nvalidate_maker_order_side(maker_order, derived)?;\n// after: normalize provider side explicitly before comparing\nlet normalized = match maker_order.side.as_str() {\n    \"BUY\" => OrderSide::Buy,\n    \"SELL\" => OrderSide::Sell,\n    other => anyhow::bail!(\"unknown provider side {other}\"),\n};\nanyhow::ensure!(normalized == derived, ...);","handlingStrategy":"validation","validationCode":"fn sides_agree(provider_side: &str, derived: OrderSide) -> bool {\n    OrderSide::from(provider_side) == derived\n}","typeGuard":"fn normalize_provider_side(s: &str) -> Option<OrderSide> {\n    match s.to_ascii_uppercase().as_str() {\n        \"BUY\" => Some(OrderSide::Buy),\n        \"SELL\" => Some(OrderSide::Sell),\n        _ => None,\n    }\n}","tryCatchPattern":"let derived_side = match validate_maker_order_side(&maker_order, &trade) {\n    Ok(side) => side,\n    Err(e) => { warn!(\"side mismatch for order {}: {e}\", maker_order.order_id); refresh_order_and_retry()? }\n};","preventionTips":["Normalize the provider side string explicitly before comparison","Confirm which source (REST vs trade data) is authoritative for side","Refresh cached REST orders before reconciling against fresh trades"],"tags":["rust","reconciliation","polymarket","side-mismatch"],"backgroundTag":"invalid-argument-value","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"}