nautechsystems/nautilus_trader · error

Failed to send delete order hash index command: {e}

Error message

Failed to send delete order hash index command: {e}

What it means

After set-index cleanup, delete_order removes the order id from hash indexes (order-to-position and order-to-client mappings). This error is the same channel-send failure raised specifically for those hash index delete commands when the writer task's receiver is gone.

Source

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

        ];

        for index_key in &index_keys {
            let key = (*index_key).to_string();
            let payload = vec![order_id_bytes.clone()];
            let op = DatabaseCommand::new(DatabaseOperation::Delete, key, Some(payload));
            self.tx
                .send(op)
                .map_err(|e| anyhow::anyhow!("Failed to send delete order index command: {e}"))?;
        }

        // Delete from hash indexes
        let hash_indexes = [INDEX_ORDER_POSITION, INDEX_ORDER_CLIENT];
        for index_key in &hash_indexes {
            let key = (*index_key).to_string();
            let payload = vec![order_id_bytes.clone()];
            let op = DatabaseCommand::new(DatabaseOperation::Delete, key, Some(payload));
            self.tx.send(op).map_err(|e| {
                anyhow::anyhow!("Failed to send delete order hash index command: {e}")
            })?;
        }

        Ok(())
    }

    /// Delete the given position from the database with full index cleanup.
    ///
    /// # Errors
    ///
    /// Returns an error if the command cannot be sent to the background task channel.
    pub fn delete_position(&self, position_id: &PositionId) -> anyhow::Result<()> {
        let position_id_bytes = Bytes::from(position_id.to_string());

        // Delete the position itself
        let key = format!("{POSITIONS}{REDIS_DELIMITER}{position_id}");
        let op = DatabaseCommand::new(DatabaseOperation::Delete, key, None);
        self.tx

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Reconnect/restart the cache writer task and retry delete_order.
  2. Ensure deletes happen while the trading node and its cache task are alive.
  3. Investigate why the writer task exited (Redis outage, panic) using earlier log entries.
  4. Audit Redis hash indexes (INDEX_ORDER_POSITION / INDEX_ORDER_CLIENT) for orphaned entries after such a failure.
Defensive patterns

Strategy: retry

Try / catch

if let Err(e) = cache.delete_order(&client_order_id) {
    if e.to_string().contains("hash index command") {
        // reconnect and retry; then clean orphaned hash entries
    }
}

Prevention

When it happens

Trigger: Calling delete_order with a dead command-channel receiver, occurring after the order delete and set-index deletes were queued.

Common situations: Mid-shutdown deletes, Redis connection loss that killed the writer, or a cache adapter that was constructed but whose command loop exited.

Related errors


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