{"record":{"id":"ff631039338ced07","repo":"nautechsystems/nautilus_trader","slug":"coinbase-fill-has-unknown-order-side","errorCode":null,"errorMessage":"Coinbase fill has unknown order side","messagePattern":"Coinbase fill has unknown order side","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/coinbase/src/http/parse.rs","lineNumber":501,"sourceCode":"/// Converts a Coinbase order side to the Nautilus [`Option<OrderSide>`].\npub fn parse_order_side_optional(side: &CoinbaseOrderSide) -> Option<OrderSide> {\n    match side {\n        CoinbaseOrderSide::Buy => Some(OrderSide::Buy),\n        CoinbaseOrderSide::Sell => Some(OrderSide::Sell),\n        CoinbaseOrderSide::Unknown => None,\n    }\n}\n\n/// Converts a Coinbase order side to a Nautilus [`OrderSide`].\n///\n/// # Errors\n///\n/// Returns an error when Coinbase supplies an unknown side.\npub fn parse_order_side(side: &CoinbaseOrderSide) -> anyhow::Result<OrderSide> {\n    match side {\n        CoinbaseOrderSide::Buy => Ok(OrderSide::Buy),\n        CoinbaseOrderSide::Sell => Ok(OrderSide::Sell),\n        CoinbaseOrderSide::Unknown => anyhow::bail!(\"Coinbase fill has unknown order side\"),\n    }\n}\n\n/// Converts a Coinbase order status to the Nautilus [`OrderStatus`].\n///\n/// `Pending` and `Queued` are transient pre-`Open` states the venue passes\n/// through after acknowledging the order. They are mapped to `Accepted`\n/// (rather than `Submitted`) so user-channel updates that race the REST\n/// `OrderAccepted` event do not appear as a backwards transition to the\n/// reconciler. `Open` also maps to `Accepted` because Nautilus differentiates\n/// the initial accept event from later partial-fill states; callers should\n/// promote the status to `PartiallyFilled` / `Filled` based on `filled_qty`.\npub fn parse_order_status(status: CoinbaseOrderStatus) -> OrderStatus {\n    match status {\n        CoinbaseOrderStatus::Pending | CoinbaseOrderStatus::Queued | CoinbaseOrderStatus::Open => {\n            OrderStatus::Accepted\n        }\n        CoinbaseOrderStatus::Filled => OrderStatus::Filled,","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/coinbase/src/http/parse.rs#L483-L519","documentation":"Coinbase fill reports carry an order side that is mapped to Nautilus OrderSide. If Coinbase reports the side as Unknown (missing/unexpected value in the fill payload), parse_order_side refuses to guess and returns this error, since a fill without a valid side cannot be applied to a position.","triggerScenarios":"parse_fill_report processing a Coinbase fill JSON whose side field is absent or an unrecognized value, deserializing to CoinbaseOrderSide::Unknown.","commonSituations":"Coinbase API schema changes or partial fill records with missing side; proxy/CDN mangling responses; processing historical fills from an API version with different side casing.","solutions":["Inspect the raw fill payload from Coinbase to see what side value was returned","Update the CoinbaseOrderSide deserializer if Coinbase changed its side representation","Drop or quarantine fills with Unknown side instead of feeding them into position accounting"],"exampleFix":"// before\nlet side = parse_order_side(&fill.side)?;\n// after\nlet Ok(side) = parse_order_side(&fill.side) else { log::warn!(\"skipping fill with unknown side\"); continue; };","handlingStrategy":"try-catch","validationCode":"if fill.side == CoinbaseOrderSide::Unknown { return Err(\"fill side missing\".into()); }","typeGuard":"fn known_side(s: &CoinbaseOrderSide) -> Option<OrderSide> {\n    parse_order_side(s).ok()\n}","tryCatchPattern":"let side = match parse_order_side(&fill.side) {\n    Ok(s) => s,\n    Err(e) => { log::warn!(\"drop fill {}: {e}\", fill.fill_id); continue; }\n};","preventionTips":["Log raw fill payloads to detect Coinbase schema changes early","Pin and monitor adapter versions against Coinbase API changelog","Skip rather than panic on malformed fills in reconciliation loops"],"tags":["rust","coinbase","fills","parsing"],"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-14T05:17:10.506Z"}