{"record":{"id":"6bf243b85c22a635","repo":"nautechsystems/nautilus_trader","slug":"fill-maps-to-non-open-position-position-id","errorCode":null,"errorMessage":"fill {} maps to non-open position {position_id}","messagePattern":"fill (.+?) maps to non-open position (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/live/src/execution/manager.rs","lineNumber":2898,"sourceCode":"        }\n\n        let Some(position_id) = mapped_position_id else {\n            return Ok(PositionFillReportPreparation::Unattributed);\n        };\n        let position = cache.position(&position_id).ok_or_else(|| {\n            anyhow::anyhow!(\n                \"fill {} maps to position {position_id}, which is not cached\",\n                report.trade_id,\n            )\n        })?;\n\n        anyhow::ensure!(\n            position.account_id == report.account_id\n                && position.instrument_id == report.instrument_id,\n            \"fill {} maps to position {position_id} with a different account or instrument\",\n            report.trade_id,\n        );\n        anyhow::ensure!(\n            position.is_open(),\n            \"fill {} maps to non-open position {position_id}\",\n            report.trade_id,\n        );\n        anyhow::ensure!(\n            !position.is_opposite_side(report.order_side) || report.last_qty <= position.quantity,\n            \"fill {} without a venue position ID would cross position {position_id}\",\n            report.trade_id,\n        );\n\n        report.venue_position_id = Some(position_id);\n        Ok(PositionFillReportPreparation::Ready)\n    }\n\n    #[cfg(feature = \"node\")]\n    fn has_active_inferred_fill(order: &OrderAny) -> anyhow::Result<bool> {\n        let events = order.events();\n        let trade_ids = order.trade_ids();","sourceCodeStart":2880,"sourceCodeEnd":2916,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/execution/manager.rs#L2880-L2916","documentation":"The fill was mapped to a cached position that is already closed (is_open() is false). Applying a fill to a closed position would resurrect inconsistent state, so the manager fails the report preparation.","triggerScenarios":"A fill arrives referencing a position_id whose cached Position already emitted a Closed event - e.g. a late/duplicate venue fill after the position was flattened, or a duplicate report delivered after the closing fill was processed.","commonSituations":"Late fills from the venue arriving after an offsetting order closed the position; duplicate trade reports on reconnect/replay; venues emitting fills for positions the adapter already considered closed due to netting.","solutions":["Deduplicate trade reports by trade_id before processing so replayed fills are ignored","Configure reconciliation/idempotency so late duplicate fills are dropped rather than applied","Check venue netting behavior and configure the node's account type (netting vs hedging) to match","Review adapter report replay logic to not re-emit already-processed fills"],"exampleFix":"// before (no dedup on replay)\nfor report in reports { self.handle_report(report); }\n// after\nfor report in reports {\n    if self.processed_trade_ids.insert(report.trade_id) {\n        self.handle_report(report);\n    }\n}","handlingStrategy":"validation","validationCode":"if let Some(pos) = cache.position(&position_id) {\n    if !pos.is_open() {\n        // drop or dedupe this late fill instead of applying it\n    }\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"non-open position\") => {\n        // treat as duplicate/late fill: log and discard\n    }\n    other => other?,\n}","preventionTips":["Deduplicate reports by trade_id before processing","Handle reconnect replays idempotently","Match netting/hedging config to venue behavior"],"tags":["rust","live-execution","position-state","duplicate-report"],"backgroundTag":"invalid-state-transition","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"}