nautechsystems/nautilus_trader · error

Failed to send query add_account to database message handler

Error message

Failed to send query add_account to database message handler: {e}

What it means

Thrown by `add_account` when the `DatabaseQuery::AddAccount` message cannot be sent to the database message-handler task because its receiver has been dropped. Note `account_last_event(account)` is evaluated first, so a SendError is the only source of this message. The account state is not persisted.

Source

Thrown at crates/infrastructure/src/sql/cache.rs:944

    fn add_instrument_close(&self, close: &InstrumentClose) -> anyhow::Result<()> {
        self.tx
            .send(DatabaseQuery::AddInstrumentClose(*close))
            .map_err(|e| {
                anyhow::anyhow!(
                    "Failed to send query add_instrument_close to database message handler: {e}"
                )
            })
    }

    fn add_synthetic(&self, _synthetic: &SyntheticInstrument) -> anyhow::Result<()> {
        todo!()
    }

    fn add_account(&self, account: &AccountAny) -> anyhow::Result<()> {
        let query = DatabaseQuery::AddAccount(account_last_event(account)?, false);
        self.tx.send(query).map_err(|e| {
            anyhow::anyhow!("Failed to send query add_account to database message handler: {e}")
        })
    }

    fn add_order(&self, order: &OrderAny, client_id: Option<ClientId>) -> anyhow::Result<()> {
        let query = DatabaseQuery::AddOrder(order_initialized_event(order), client_id);
        self.tx.send(query).map_err(|e| {
            anyhow::anyhow!("Failed to send query add_order to database message handler: {e}")
        })
    }

    fn add_order_snapshot(&self, snapshot: &OrderSnapshot) -> anyhow::Result<()> {
        let query = DatabaseQuery::AddOrderSnapshot(snapshot.to_owned());
        self.tx.send(query).map_err(|e| {
            anyhow::anyhow!(
                "Failed to send query add_order_snapshot to database message handler: {e}"
            )
        })
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the adapter's background task is alive before writing accounts.
  2. Look for receiver-task panics in logs.
  3. Reconnect/recreate the adapter and retry.
  4. In Python, wrap account persistence so it stops once the adapter is disconnected.
Defensive patterns

Strategy: try-catch

Validate before calling

if not cache_db_adapter.is_running:
    raise RuntimeError("Cannot add_account: adapter not running")

Try / catch

try:
    cache.add_account(account)
except RuntimeError as e:
    logger.error("Account persistence failed (writer stopped): %s", e)

Prevention

When it happens

Trigger: Calling `add_account` (via `py_add_account`) when the writer task is gone: adapter stopped, handler panicked, or shutdown in progress.

Common situations: Persisting account updates after the SQL adapter disconnected; shutdown ordering issues in live deployments.

Related errors


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