nautechsystems/nautilus_trader · error

load_index_order_client channel closed: {e}

Error message

load_index_order_client channel closed: {e}

What it means

Loads the (client_order_id → client_id) index from Redis through the same worker-thread + mpsc pattern. This error means `blocking_recv(&rx)` got `RecvError` because the sending task terminated without sending — a panic, drop, or early exit in the worker.

Source

Thrown at crates/infrastructure/src/redis/cache.rs:1504

        blocking_recv(&rx)
            .map_err(|e| anyhow::anyhow!("load_index_order_position channel closed: {e}"))?
    }

    fn load_index_order_client(&self) -> anyhow::Result<AHashMap<ClientOrderId, ClientId>> {
        let con = self.database.con.clone();
        let trader_key = self.database.trader_key.clone();
        let (tx, rx) = mpsc::channel();

        get_runtime().spawn(async move {
            let result = DatabaseQueries::load_index_order_client(&con, &trader_key).await;
            if let Err(e) = tx.send(result) {
                log::error!("Failed to send load_index_order_client result: {e:?}");
            }
        });

        blocking_recv(&rx)
            .map_err(|e| anyhow::anyhow!("load_index_order_client channel closed: {e}"))?
    }

    async fn load_currency(&self, code: &Ustr) -> anyhow::Result<Option<Currency>> {
        DatabaseQueries::load_currency(
            &self.database.con,
            &self.database.trader_key,
            code,
            self.encoding(),
        )
        .await
    }

    async fn load_instrument(
        &self,
        instrument_id: &InstrumentId,
    ) -> anyhow::Result<Option<InstrumentAny>> {
        DatabaseQueries::load_instrument(
            &self.database.con,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check logs right before the error for the real cause (panic trace or send-failure log)
  2. Verify the index_order_client keys in Redis deserialize under the current encoding; delete/rewrite bad entries
  3. Retry the load once the Redis connection is stable
  4. Propagate worker errors through the channel to avoid this opaque RecvError wrapper
Defensive patterns

Strategy: retry

Try / catch

// Rust
match cache.load_index_order_client() {
    Ok(index) => index,
    Err(e) if e.to_string().contains("channel closed") => {
        log::warn!("retrying index_order_client load after channel close: {e:#}");
        cache.load_index_order_client()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling the client-order index load during cache load when the spawned task fails before `tx.send(result)` (deserialization panic on index entries, connection drop inside the task, task cancellation).

Common situations: Corrupt or schema-changed index data in Redis; runtime shutdown during startup; incompatible data written by an older nautilus version.

Related errors


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