nautechsystems/nautilus_trader · error · anyhow::Error
OrderList denied: duplicate {order_list.id}
Error message
OrderList denied: duplicate {order_list.id} What it means
When submitting an order list, the strategy checks `cache.order_list_exists(&order_list.id)`; if a list with the same ID is already in the cache the submission is rejected with `OrderList denied: duplicate {order_list.id}`. This guards against submitting the same logical order list twice (double-fire of the same request).
Source
Thrown at crates/trading/src/strategy/mod.rs:272
core.order_factory().create_list(&mut orders, ts_init)
};
if let Err(e) = order_list.validate() {
log::error!("OrderList denied: {e}");
anyhow::bail!("OrderList denied: {e}");
}
{
let cache_rc = core.cache_rc();
let mut cache = cache_rc.try_borrow_mut().map_err(|_| {
anyhow::anyhow!(
"Cannot submit order list {}: cache is currently borrowed",
order_list.id
)
})?;
if cache.order_list_exists(&order_list.id) {
anyhow::bail!("OrderList denied: duplicate {}", order_list.id);
}
for order in &orders {
if cache.order_exists(&order.client_order_id()) {
anyhow::bail!(
"Order in list denied: duplicate {}",
order.client_order_id()
);
}
}
cache.add_order_list(order_list.clone())?;
for order in &orders {
cache.add_order(order.clone(), position_id, client_id, true)?;
}
}
for order in &orders {View on GitHub (pinned to 18893faf8b)
Solutions
- Check `self.cache.order_list_exists(order_list.id)` before submitting, or make the call idempotent.
- On retry, create a fresh order list via the OrderFactory so new client_order_ids are generated.
- Deduplicate your signal/event source so the same condition does not trigger submission twice.
- Log the order_list.id on submission and skip if it matches the last submitted list.
Example fix
// before
self.submit_order_list(order_list) # called again on retry -> duplicate
// after
if not self.cache.order_list_exists(order_list.id):
self.submit_order_list(order_list)
else:
self.log.warning(f'Order list {order_list.id} already submitted') Defensive patterns
Strategy: validation
Validate before calling
if self.cache.order_list_exists(order_list.id):
self.log.warning(f'{order_list.id} already submitted — skipping')
else:
self.submit_order_list(order_list) Type guard
def can_submit_order_list(strategy, order_list):
return not strategy.cache.order_list_exists(order_list.id) Try / catch
try:
if not self.cache.order_list_exists(order_list.id):
self.submit_order_list(order_list)
except Exception as e:
self.log.error(f'Order list submission failed: {e}') Prevention
- Check cache.order_list_exists before every submission
- Create a fresh list (new client_order_ids) for retries rather than resubmitting
- Deduplicate signals/events that trigger submission
- Track submitted list IDs in strategy state as a second guard
When it happens
Trigger: Calling `submit_order_list` twice with the same OrderList / same client_order_id set — e.g. retrying a submission after an error, or calling submit from both a handler and a timer for the same list object.
Common situations: Retry logic that re-submits the original list after a transient failure without creating a new one; duplicate signal processing creating identical lists; replayed events in backtests resubmitting historical orders; code path that submits on both on_data and on_bar for the same condition.
Related errors
- IDEMPOTENT_DUPLICATE
- External order claim for {instrument_id} appears more than o
- OrderList denied: duplicate {}
- Failed to reserve execution intent for signer {} on chain {}
- Failed to commit replacement transaction: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/140a53447d25ea6c.
Report an issue: GitHub.