nautechsystems/nautilus_trader · error

No instrument ID for command

Error message

No instrument ID for command

What it means

`ExecutionCommand::instrument_id()` is a total accessor over all execution command variants; because `QueryAccount` is account-scoped and carries no instrument ID, matching it reaches an explicit `panic!`. The doc-comment documents this: the method must only be called on commands that are instrument-scoped. It signals a caller-side dispatch bug, not bad user input.

Source

Thrown at crates/common/src/messages/execution/mod.rs:202

    }

    /// Returns the instrument ID for the command.
    ///
    /// # Panics
    ///
    /// Panics if the command is `QueryAccount` which does not have an instrument ID.
    #[must_use]
    pub const fn instrument_id(&self) -> InstrumentId {
        match self {
            Self::SubmitOrder(command) => command.instrument_id,
            Self::SubmitOrderList(command) => command.instrument_id,
            Self::ModifyOrder(command) => command.instrument_id,
            Self::ModifyOrders(command) => command.instrument_id,
            Self::CancelOrder(command) => command.instrument_id,
            Self::CancelOrders(command) => command.instrument_id,
            Self::CancelAllOrders(command) => command.instrument_id,
            Self::QueryOrder(command) => command.instrument_id,
            Self::QueryAccount(_) => panic!("No instrument ID for command"),
        }
    }

    #[must_use]
    pub const fn ts_init(&self) -> UnixNanos {
        match self {
            Self::SubmitOrder(command) => command.ts_init,
            Self::SubmitOrderList(command) => command.ts_init,
            Self::ModifyOrder(command) => command.ts_init,
            Self::ModifyOrders(command) => command.ts_init,
            Self::CancelOrder(command) => command.ts_init,
            Self::CancelOrders(command) => command.ts_init,
            Self::CancelAllOrders(command) => command.ts_init,
            Self::QueryOrder(command) => command.ts_init,
            Self::QueryAccount(command) => command.ts_init,
        }
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Match the command variant first and handle `QueryAccount` separately before calling `instrument_id()`.
  2. Pattern-match and return `Option<InstrumentId>` at the call site instead of using the total accessor.
  3. Reorder routing logic so account commands are processed before any instrument_id extraction.
  4. If the panic occurs, log the command variant to confirm an unhandled QueryAccount is reaching instrument-scoped processing.

Example fix

// before
let instrument_id = command.instrument_id();
process(instrument_id);
// after
match command {
    ExecutionCommand::QueryAccount(cmd) => process_account(cmd),
    _ => process(command.instrument_id()),
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Guard before calling the accessor
if matches!(command, ExecutionCommand::QueryAccount(_)) {
    return; // account commands have no instrument_id
}
let instrument_id = command.instrument_id();

Type guard

fn command_instrument_id(cmd: &ExecutionCommand) -> Option<InstrumentId> {
    match cmd {
        ExecutionCommand::QueryAccount(_) => None,
        other => Some(other.instrument_id()),
    }
}

Prevention

When it happens

Trigger: Calling `command.instrument_id()` on an `ExecutionCommand::QueryAccount(_)` — e.g. in `process_trading_command` or any routing/logging code that calls the accessor before filtering out account-scoped commands.

Common situations: New command handlers that iterate all `ExecutionCommand` variants generically; refactors that add a `QueryAccount` path without excluding it from instrument-scoped logic; debug logging of commands that blindly extracts instrument_id.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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