nautechsystems/nautilus_trader · error · anyhow::Error

Cannot submit order list {order_list.id}: cache is currently

Error message

Cannot submit order list {order_list.id}: cache is currently borrowed

What it means

Before adding the order list to the Cache, `submit_order_list` attempts a mutable borrow of the shared Cache via `try_borrow_mut`. If the Cache is already borrowed on the same thread the submission fails with `Cannot submit order list {order_list.id}: cache is currently borrowed`. This is a single-threaded re-entrancy/borrow conflict, not a lock contention issue.

Source

Thrown at crates/trading/src/strategy/mod.rs:265

        let strategy_id = registered_strategy_id(core)?;
        let ts_init = core.clock_mut().timestamp_ns();

        // TODO: Replace with fluent builder API for order list construction
        let order_list = if orders.first().is_some_and(|o| o.order_list_id().is_some()) {
            OrderList::from_orders(&orders, ts_init)
        } else {
            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()
                    );
                }
            }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Defer the submission out of the nested context (e.g. queue the order list and submit from `on_start` or a timer/event after dispatch completes).
  2. Drop any retained cache borrow guards before calling `submit_order_list`.
  3. Avoid submitting orders while iterating cache collections in the same call stack.
  4. If triggered by an exec algorithm, restructure so child orders are submitted from a fresh event-cycle callback.

Example fix

// before
for order in self.cache.orders_open(...):  # holds cache borrow
    self.submit_order_list(build_list(order))  # re-entrant borrow -> error
// after
pending = [build_list(o) for o in list(self.cache.orders_open(...))]
for ol in pending:
    self.submit_order_list(ol)  # submitted after iteration completes
Defensive patterns

Strategy: fallback

Try / catch

try:
    self.submit_order_list(order_list)
except Exception as e:
    if 'cache is currently borrowed' in str(e):
        self._deferred_lists.append(order_list)  # submit later from a timer/event
    else:
        raise

Prevention

When it happens

Trigger: Calling `submit_order_list` while a mutable cache borrow is outstanding — e.g. from inside a callback while the engine dispatch holds the cache, or while user code holds a cache handle obtained earlier.

Common situations: Submitting orders from within `on_event`/handlers nested inside a cache-borrowing code path; retaining a cache borrow guard across the submit call; custom adapters or exec algorithms re-entering submission during cache iteration.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/0f9c0d8bf2d36d60. Report an issue: GitHub.