{"record":{"id":"616bb289e2f1e3e6","repo":"nautechsystems/nautilus_trader","slug":"fill-position-id-venue-position-id-conflicts","errorCode":null,"errorMessage":"fill {} position ID {venue_position_id} conflicts with cached order position {mapped_position_id}","messagePattern":"fill (.+?) position ID (.+?) conflicts with cached order position (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/live/src/execution/manager.rs","lineNumber":2861,"sourceCode":"                \"fill {} conflicts with cached order {}\",\n                report.trade_id,\n                order.client_order_id(),\n            );\n        }\n\n        let hedge_context = report.venue_position_id.is_some()\n            || venue_reports\n                .iter()\n                .any(|venue_report| venue_report.venue_position_id.is_some());\n        let mapped_position_id = client_order_id\n            .and_then(|client_order_id| cache.position_id(&client_order_id))\n            .copied();\n\n        if hedge_context\n            && let (Some(venue_position_id), Some(mapped_position_id)) =\n                (report.venue_position_id, mapped_position_id)\n        {\n            anyhow::ensure!(\n                venue_position_id == mapped_position_id,\n                \"fill {} position ID {venue_position_id} conflicts with cached order position {mapped_position_id}\",\n                report.trade_id,\n            );\n        }\n\n        if let Some(order) = order\n            && Self::has_active_inferred_fill(&order)?\n        {\n            return Ok(PositionFillReportPreparation::InferredOverlap);\n        }\n\n        if !hedge_context {\n            return Ok(PositionFillReportPreparation::Ready);\n        }\n\n        if report.venue_position_id.is_some() {\n            return Ok(PositionFillReportPreparation::Ready);","sourceCodeStart":2843,"sourceCodeEnd":2879,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/execution/manager.rs#L2843-L2879","documentation":"In hedge mode (hedging context), a fill report's venue_position_id is compared to the position ID mapped to the cached order. If they differ, the fill is attributed to a different position than the order's mapping, so the manager rejects it to keep position hedging consistent.","triggerScenarios":"A fill arrives with venue_position_id P1 while the cached order's position mapping says P2, under a hedging account. Happens when the venue reassigns positions, when the adapter invents position IDs per fill, or when cache position mappings are stale after restart/reconciliation.","commonSituations":"Hedging mode with venues that aggregate fills into positions differently than the adapter assumed; netting venue behind a hedging-configured node; adapter generating synthetic position IDs that drift from cached ones.","solutions":["Make the adapter return the venue_position_id consistently for all fills of the same position","Verify the node is configured with the correct netting vs hedging account type matching the venue","Re-reconcile cached position mappings with venue state after reconnects","Purge stale cache entries whose position mappings no longer match the venue"],"exampleFix":"// before (synthetic per-fill position ID)\nreport.venue_position_id = Some(VenuePositionId::new(uuid::Uuid::new_v4().to_string()));\n// after (venue-reported position, reused across fills)\nreport.venue_position_id = venue_fill.position_id.map(VenuePositionId::from);","handlingStrategy":"validation","validationCode":"if hedge_context {\n    if let (Some(vp), Some(mp)) = (report.venue_position_id, cache.mapped_position_id(&client_order_id)) {\n        assert_eq!(vp, mp);\n    }\n}","typeGuard":"fn position_mapping_consistent(report: &TradeReport, order: &OrderAny) -> bool {\n    report.venue_position_id.map_or(true, |p| {\n        order.position_id().map_or(true, |op| op == p)\n    })\n}","tryCatchPattern":null,"preventionTips":["Configure netting vs hedging account type to match the venue's real behavior","Reconcile position mappings after every reconnect","Never synthesize position IDs per fill; always propagate the venue's ID"],"tags":["rust","live-execution","position-mapping","hedging"],"backgroundTag":"internal-invariant-violation","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"}