{"record":{"id":"243be8a551c0dd7a","repo":"nautechsystems/nautilus_trader","slug":"no-position-fragments-found-for-fill","errorCode":null,"errorMessage":"no position fragments found for fill {}","messagePattern":"no position fragments found for fill (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/execution/src/engine/mod.rs","lineNumber":3908,"sourceCode":"                let PositionReplayEvent::Filled(fill) = replay_event else {\n                    continue;\n                };\n\n                if fill.client_order_id != event.client_order_id || fill.trade_id != event.trade_id\n                {\n                    continue;\n                }\n                let split_rank = if fill.event_id == source_event_id {\n                    0\n                } else if fill.causation_id == Some(source_event_id) {\n                    1\n                } else {\n                    continue;\n                };\n                fragments.push((position.id, split_rank, fill.last_qty, fill.commission));\n            }\n        }\n        anyhow::ensure!(\n            !fragments.is_empty(),\n            \"no position fragments found for fill {}\",\n            event.trade_id\n        );\n        fragments.sort_by_key(|(_, split_rank, _, _)| *split_rank);\n\n        let mut allocations = IndexMap::<PositionId, (Quantity, Option<Money>)>::new();\n        let mut remaining_qty = event.voided_qty;\n        for (position_id, _, quantity, _) in fragments.iter().rev() {\n            if remaining_qty.is_zero() {\n                break;\n            }\n            let removed = remaining_qty.min(*quantity);\n            allocations\n                .entry(*position_id)\n                .and_modify(|allocation| allocation.0 = allocation.0 + removed)\n                .or_insert((removed, None));\n            remaining_qty = remaining_qty - removed;","sourceCodeStart":3890,"sourceCodeEnd":3926,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/execution/src/engine/mod.rs#L3890-L3926","documentation":"While splitting a fill across open positions (fragment computation for position events), the engine accumulates fragments from matching positions and then asserts via anyhow::ensure! that at least one fragment was produced. Zero fragments means the fill's quantity could not be attributed to any known open position, so position bookkeeping cannot proceed.","triggerScenarios":"Processing a fill (event.trade_id) in the position-fragment path when every candidate position is skipped (e.g. position ids no longer open or quantities don't match), leaving the fragments vec empty at the ensure!.","commonSituations":"Cache does not contain the positions the fill should close (stale or rebuilt cache); fill arrives for a position already closed by a prior duplicate fill; OEMS position state diverged from broker state after reconnect; reconciliation applying fills out of order.","solutions":["Confirm the cache holds the open position(s) the fill applies to (check position ids and instrument in cache.positions).","Re-run reconciliation/mass-status handling so local positions match the broker before processing further fills.","Check for duplicate fills that already closed the target position earlier in the stream.","Reload the cache or resubscribe/refresh position state, then replay the fill."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// confirm the positions the fill targets are open before processing\nlet open = cache.positions(Some(instrument_id), None);\nif open.is_empty() {\n    // run reconciliation before applying the fill\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = process_fill(event) {\n    if e.to_string().contains(\"no position fragments found\") {\n        // reconcile with broker state, then replay the fill\n    }\n}","preventionTips":["Run reconciliation after every reconnect so local positions match the broker.","Reject duplicate fills that would double-close a position.","Keep position snapshots persisted with the cache so fragments can always resolve."],"tags":["execution-engine","positions","fills","rust"],"backgroundTag":"empty-result-set","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"}