nautechsystems/nautilus_trader · warning · anyhow::Error
terminal report for {} has unaccounted fills; waiting for fi
Error message
terminal report for {} has unaccounted fills; waiting for fill reports What it means
When processing an OrderStatusReport that is terminal (e.g. FILLED, CANCELED), the manager ensures the report's filled quantity accounts for all fills already known to the order. If terminal_report_has_missing_fills is true, there are unaccounted fills - the manager refuses to apply the terminal event and waits for the outstanding fill reports so no fill is lost.
Source
Thrown at crates/live/src/execution/manager.rs:4720
&order_report,
account_id,
instrument,
&[],
true,
None,
None,
);
Some(events)
}
fn reconcile_order_report(
&self,
order: &OrderAny,
report: &OrderStatusReport,
instrument: Option<&InstrumentAny>,
commission_client: Option<&dyn ExecutionClient>,
) -> anyhow::Result<Vec<OrderEventAny>> {
anyhow::ensure!(
!terminal_report_has_missing_fills(report, order.filled_qty()),
"terminal report for {} has unaccounted fills; waiting for fill reports",
order.client_order_id(),
);
let ts_now = self.clock.borrow().timestamp_ns();
let commission = if matches!(
report.order_status,
OrderStatus::PartiallyFilled | OrderStatus::Filled
) && report.filled_qty > order.filled_qty()
&& let Some(instrument) = instrument
{
let fill_qty = report.filled_qty - order.filled_qty();
Self::resolve_inferred_fill_commission(
commission_client,
instrument,
fill_qty,
incremental_inferred_fill_price_and_liquidity(order, report, instrument),
)?View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the adapter delivers fill (trade) reports and that nothing drops them (check stream subscriptions)
- Retry/re-request the status report after fills arrive - the manager waits, so verify the fill stream is connected
- Check venue-specific ordering guarantees; if the venue sends FILLED status first, defer terminal handling until fills are in
- Review adapter reconciliation logic so status reports don't bypass fill reports
Example fix
// before (adapter skips individual trade reports)
if status.is_terminal() { self.generate_order_events(status); }
// after (emit fills first, let manager verify)
for fill in venue_fills { self.generate_fill_events(fill); }
self.generate_order_events(status); Defensive patterns
Strategy: retry
Validate before calling
if terminal_report_has_missing_fills(&report, order.filled_qty()) {
// wait for fill reports or re-request the status report later
} Try / catch
match result {
Err(e) if e.to_string().contains("unaccounted fills") => {
// schedule re-request of the status report after fill reports arrive
}
other => other?,
} Prevention
- Subscribe to and verify the venue's fill/trade stream health
- Keep both status and fill report paths enabled in adapter config
- Test with venues whose status and fill deliveries race
When it happens
Trigger: A status report arrives with a terminal status while the venue's fill reports for the executed quantity haven't all been received/processed yet (e.g. FILLED status seen before the corresponding TradeReports).
Common situations: Venues that emit order status updates and trade fills over separate streams with different latencies; reconciliation snapshots taken mid-flight; adapters that suppress individual fill reports and rely only on status reports.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- fill {} client order ID {report_client_order_id} conflicts w
- fill {} order side or venue order ID differs from cached ord
- fill {} position ID {venue_position_id} conflicts with cache
- fill {} maps to position {position_id}, which is not cached
- fill {} maps to position {position_id} with a different acco
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4a79b41c3bb614e0.
Report an issue: GitHub.