nautechsystems/nautilus_trader · error

Query account ID {} does not match client account ID {}

Error message

Query account ID {} does not match client account ID {}

What it means

The blockchain execution client is bound to a single account and only handles commands targeting that account. query_account validates that the incoming QueryAccount command's account_id matches the client's configured core.account_id before processing, throwing this error otherwise. It is a routing/safety check preventing cross-account balance reporting.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:5806

    }

    fn cancel_all_orders(&self, cmd: CancelAllOrders) -> anyhow::Result<()> {
        log::warn!(
            "Cancel-all for {} is not supported on the blockchain execution client",
            cmd.instrument_id
        );
        Ok(())
    }

    fn batch_cancel_orders(&self, cmd: BatchCancelOrders) -> anyhow::Result<()> {
        for cancel in cmd.cancels {
            self.cancel_order(cancel)?;
        }
        Ok(())
    }

    fn query_account(&self, cmd: QueryAccount) -> anyhow::Result<()> {
        anyhow::ensure!(
            cmd.account_id == self.core.account_id,
            "Query account ID {} does not match client account ID {}",
            cmd.account_id,
            self.core.account_id
        );
        anyhow::ensure!(self.core.is_started(), "Execution client is not started");

        let balances = self.wallet_balance.lock().as_account_balances()?;
        self.generate_account_state(
            balances,
            vec![],
            true,
            get_atomic_clock_realtime().get_time_ns(),
            None,
        )
    }

    fn query_order(&self, cmd: QueryOrder) -> anyhow::Result<()> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the account_id in the failing QueryAccount command and correct it to match the client's configured account
  2. Verify the execution client config (account/credentials) matches the account you intend to query
  3. Re-register/restart the client so the message bus routes commands to the client bound to that account_id
  4. If running multiple accounts, ensure each QueryAccount is delivered to the correct client instance

Example fix

// before
let cmd = QueryAccount::new(account_id: "BK-001");
client.query_account(cmd)?;
// after
let cmd = QueryAccount::new(account_id: client.core.account_id);
client.query_account(cmd)?;
Defensive patterns

Strategy: validation

Validate before calling

// before sending the command
if cmd.account_id != client.account_id() {
    return Err(anyhow::anyhow!("routing error: cmd {} vs client {}", cmd.account_id, client.account_id()));
}
client.query_account(cmd)?;

Type guard

fn targets_client(cmd: &QueryAccount, client: &ExecutionClient) -> bool {
    cmd.account_id == client.core.account_id
}

Try / catch

match client.query_account(cmd) {
    Err(e) if e.to_string().contains("does not match client account ID") => {
        log::warn!("command routed to wrong client; re-dispatching by account_id");
        router.dispatch_by_account(cmd)?;
    }
    other => other,
}

Prevention

When it happens

Trigger: Sending a QueryAccount command (via the message bus or direct handle) whose account_id differs from the account_id the execution client was configured/started with.

Common situations: Multiple trading accounts configured but commands fanned out to all clients; a copy-pasted account_id in config; a stale client instance still registered on the bus after an account switch; programmatic callers constructing QueryAccount with the wrong AccountId.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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