nautechsystems/nautilus_trader · error · anyhow::Error

Batch order-client indexing is not supported by this cache d

Error message

Batch order-client indexing is not supported by this cache database

What it means

The `CacheDatabase` trait's default `index_order_clients` implementation cannot batch-index order-client claims. Non-empty claim batches are rejected by this bail; only backends that override the method with a real implementation can support batch indexing. Empty input short-circuits to Ok.

Source

Thrown at crates/common/src/cache/database.rs:524

    ///
    /// Returns an error if indexing order-position mapping fails.
    fn index_order_position(
        &self,
        client_order_id: ClientOrderId,
        position_id: PositionId,
    ) -> anyhow::Result<()>;

    /// Indexes order-client mappings as one batch operation.
    ///
    /// # Errors
    ///
    /// Returns an error if batch order-client indexing is unsupported or cannot be enqueued.
    fn index_order_clients(&self, claims: &[(ClientOrderId, ClientId)]) -> anyhow::Result<()> {
        if claims.is_empty() {
            return Ok(());
        }

        anyhow::bail!("Batch order-client indexing is not supported by this cache database")
    }

    /// Updates actor state in the cache.
    ///
    /// # Errors
    ///
    /// Returns an error if updating actor state fails.
    fn update_actor(
        &self,
        actor_id: &ActorId,
        state: &AHashMap<String, Bytes>,
    ) -> anyhow::Result<()>;

    /// Updates strategy state in the cache.
    ///
    /// # Errors
    ///
    /// Returns an error if updating strategy state fails.

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use a cache database backend that implements batch `index_order_clients` (e.g. the full Postgres/Redis backend)
  2. Implement `index_order_clients` in your custom backend to persist the claims
  3. Fall back to per-order client indexing at `add_order`/claim time instead of batch calls

Example fix

// before
struct MyDb;
impl CacheDatabase for MyDb {} // uses default that bails
// after
impl CacheDatabase for MyDb {
    fn index_order_clients(&self, claims: &[(ClientOrderId, ClientId)]) -> anyhow::Result<()> {
        for (oid, cid) in claims { self.index_one(oid, cid)?; }
        Ok(())
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

if !backend.supports_batch_order_client_indexing() {
    // fall back to per-order indexing via add_order paths
}

Type guard

fn supports_batch_indexing(db: &dyn CacheDatabase) -> bool {
    // true only for backends that override index_order_clients
    db.implements_batch_order_client_indexing()
}

Try / catch

if let Err(e) = db.index_order_clients(&claims) {
    if e.to_string().contains("not supported") {
        for (oid, cid) in &claims { db.index_one(oid, cid)?; }
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: Calling `index_order_clients` with one or more `(ClientOrderId, ClientId)` claims on a cache database backend that uses the trait-default implementation (e.g. a simple/custom backend).

Common situations: Using a custom or minimal CacheDatabase implementation without overriding `index_order_clients`; a code path newly started to use batch indexing while the configured backend predates it; swapping the cache DB backend to one lacking the feature.

Related errors


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