{"record":{"id":"06283d7dc9a2ce2b","repo":"nautechsystems/nautilus_trader","slug":"fill-client-order-id-report-client-order-id-c","errorCode":null,"errorMessage":"fill {} client order ID {report_client_order_id} conflicts with venue order mapping {venue_client_order_id}","messagePattern":"fill (.+?) client order ID (.+?) conflicts with venue order mapping (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/live/src/execution/manager.rs","lineNumber":2825,"sourceCode":"    ) -> bool {\n        check\n            .activity_revisions\n            .get(key)\n            .is_some_and(|revision| self.position_activity_revision(key) == *revision)\n    }\n\n    #[cfg(feature = \"node\")]\n    pub(crate) fn prepare_position_fill_report(\n        &self,\n        report: &mut FillReport,\n        venue_reports: &[PositionStatusReport],\n    ) -> anyhow::Result<PositionFillReportPreparation> {\n        let cache = self.cache.borrow();\n        let venue_client_order_id = cache.client_order_id(&report.venue_order_id).copied();\n        if let (Some(report_client_order_id), Some(venue_client_order_id)) =\n            (report.client_order_id, venue_client_order_id)\n        {\n            anyhow::ensure!(\n                report_client_order_id == venue_client_order_id,\n                \"fill {} client order ID {report_client_order_id} conflicts with venue order mapping {venue_client_order_id}\",\n                report.trade_id,\n            );\n        }\n        let client_order_id = report.client_order_id.or(venue_client_order_id);\n        let order = client_order_id.and_then(|id| cache.order(&id));\n        if let Some(order) = &order {\n            anyhow::ensure!(\n                order.instrument_id() == report.instrument_id\n                    && order.order_side() == report.order_side\n                    && order\n                        .account_id()\n                        .is_none_or(|account_id| account_id == report.account_id)\n                    && order\n                        .venue_order_id()\n                        .is_none_or(|venue_order_id| venue_order_id == report.venue_order_id),\n                \"fill {} conflicts with cached order {}\",","sourceCodeStart":2807,"sourceCodeEnd":2843,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/execution/manager.rs#L2807-L2843","documentation":"During preparation of a PositionFillReport in the live execution manager, the fill report's client_order_id is checked against the venue-order-ID to client-order-ID mapping cached for the venue_order_id. If both exist and differ, the fill contradicts the venue's own order mapping, indicating corrupted or mismatched report data, so the manager fails fast with anyhow::ensure!.","triggerScenarios":"An execution/fill report (TradeReport) arrives whose venue_order_id maps to client_order_id X in the cache, but the report itself carries client_order_id Y (Y != X). Typically caused by an adapter generating a new client order ID per report, duplicated venue_order_id across orders, or stale cache after restart.","commonSituations":"Custom broker/venue adapter implementations that mint fresh client_order_ids in fill reports; running a live node against a reused venue_order_id; a reconciler replaying old reports after a client_order_id scheme change or venue order amendment.","solutions":["Fix the adapter so every report for a venue_order_id carries the same client_order_id that was used to submit the order","Clear/purge stale cache entries and re-reconcile so the venue order mapping is rebuilt from the venue","Check for venue_order_id collisions (e.g. exchange reusing IDs across sessions) and include a session/epoch component in IDs","Ensure reports are processed in order and cache is not cleared between order submission and fills"],"exampleFix":"// before (adapter builds report with fresh ID)\nreport.client_order_id = Some(ClientOrderId::new(format!(\"{}-fill\", venue_order_id)));\n// after (reuse the ID registered at submission)\nreport.client_order_id = self.submitted_client_order_id(&report.venue_order_id);","handlingStrategy":"validation","validationCode":"if let (Some(coid), Some(vpid)) = (report.client_order_id, cache.client_order_id(&report.venue_order_id)) {\n    debug_assert_eq!(coid, vpid, \"fill client_order_id diverges from venue mapping\");\n}","typeGuard":"fn mapping_consistent(report: &TradeReport, cache: &Cache) -> bool {\n    cache.client_order_id(&report.venue_order_id)\n        .map_or(true, |mapped| report.client_order_id.map_or(true, |c| c == mapped))\n}","tryCatchPattern":null,"preventionTips":["Always reuse the submission-time client_order_id in every report the adapter emits","Key reports by venue_order_id, not by a per-report generated ID","Test adapters with reconciliation replay to catch ID drift early"],"tags":["rust","live-execution","report-conflict","cache-consistency"],"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"}