nautechsystems/nautilus_trader · error
fill {} is not in order history
Error message
fill {} is not in order history What it means
When processing an order event that references positions (e.g. position splits/opens derived from a fill), the engine searches the order's event history for an existing Filled event with the same trade_id to obtain the originating fill's event_id. If no prior fill in the order's history matches the incoming event's trade_id, it raises "fill {trade_id} is not in order history".
Source
Thrown at crates/execution/src/engine/mod.rs:3870
position_events
}
fn prepare_order_fill_void_positions(
&self,
order: &OrderAny,
event: &OrderFillVoided,
) -> anyhow::Result<Vec<CorrectedPosition>> {
let source_event_id = order
.events()
.into_iter()
.find_map(|order_event| match order_event {
OrderEventAny::Filled(fill) if fill.trade_id == event.trade_id => {
Some(fill.event_id)
}
_ => None,
})
.ok_or_else(|| anyhow::anyhow!("fill {} is not in order history", event.trade_id))?;
let positions: Vec<Position> = {
let cache = self.cache.borrow();
cache
.positions(
None,
Some(&event.instrument_id),
Some(&event.strategy_id),
Some(&event.account_id),
None,
)
.into_iter()
.map(|position| position.cloned())
.collect()
};
let mut fragments = Vec::new();
for position in &positions {View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the original Fill event for that trade_id was applied to the order before this dependent event (event ordering).
- Rebuild/restore the cache so the order's full event history includes the referenced fill.
- Deduplicate broker fill reports so repeated trade_ids are not re-processed as new events.
- Check reconciliation logic to ensure fills from mass status are inserted into order history before fragment computation.
Defensive patterns
Strategy: validation
Validate before calling
// before dispatching a dependent event, confirm the fill exists in order history
if !order.events().iter().any(|ev| matches!(ev,
OrderEventAny::Filled(f) if f.trade_id == event.trade_id))
{
// apply or fetch the original fill first
} Try / catch
match result {
Err(e) if e.to_string().contains("is not in order history") => {
// reload cache/replay fills, then retry the event
}
other => other?,
} Prevention
- Deduplicate broker fill reports by trade_id before applying them.
- Ensure the cache is fully rebuilt (including fill events) before reconciliation.
- Preserve event ordering so fills land before events that reference them.
When it happens
Trigger: Dispatching an order event whose trade_id does not correspond to any OrderEventAny::Filled already recorded on that order — e.g. a duplicate or replayed fill event, or an event arriving before the original fill was persisted.
Common situations: Reconciliation mass status replaying fills against orders whose history was not fully loaded from cache; duplicate broker fill reports with new trade ids; cache rebuilt without the original fill events; out-of-order event delivery from the venue.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- no position fragments found for fill {}
- Order for {} not found to determine position ID
- Skipping non-trade execution: {:?}
- Skipping execution without side: {:?}
- Coinbase fill has unknown order side
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0e27be6f79cfd078.
Report an issue: GitHub.