nautechsystems/nautilus_trader · error

Invalid `external_order_instrument_ids` instrument ID {claim

Error message

Invalid `external_order_instrument_ids` instrument ID {claim}: {e}

What it means

NautilusTrader's live node rejects `external_order_instrument_ids` entries that are not parseable InstrumentId strings. Each list element must be a valid instrument identifier (e.g. 'AAPL.NASDAQ'); the parser wraps the underlying parse error with the offending claim. Thrown at node startup while extracting the Python config list into Rust.

Source

Thrown at crates/live/src/python/node.rs:1916

        return Ok(None);
    };

    if claims.is_none() {
        return Ok(None);
    }

    if let Ok(claims) = claims.extract::<Vec<InstrumentId>>() {
        return Ok(Some(claims));
    }

    let claim_strings = claims
        .extract::<Vec<String>>()
        .map_err(|e| anyhow::anyhow!("Invalid `external_order_instrument_ids` type: {e}"))?;
    let claims = claim_strings
        .into_iter()
        .map(|claim| {
            InstrumentId::from_str(&claim).map_err(|e| {
                anyhow::anyhow!(
                    "Invalid `external_order_instrument_ids` instrument ID {claim}: {e}"
                )
            })
        })
        .collect::<anyhow::Result<Vec<_>>>()?;

    Ok(Some(claims))
}

#[cfg(feature = "examples")]
type BuiltinActorRegister = for<'py> fn(&mut LiveNode, &Bound<'py, PyAny>) -> PyResult<()>;

#[cfg(feature = "examples")]
type BuiltinStrategyRegister = for<'py> fn(&mut LiveNode, &Bound<'py, PyAny>) -> PyResult<()>;

#[cfg(feature = "examples")]
fn builtin_actor_register(type_name: &str) -> Option<BuiltinActorRegister> {
    match type_name {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Fix the offending instrument ID string to a valid InstrumentId format `SYMBOL.VENUE` (e.g. 'BTCUSDT.BINANCE')
  2. Remove empty or whitespace-only strings from the list
  3. Use InstrumentId.from_str in Python beforehand to validate each entry and surface the error at config time

Example fix

// before
{"external_order_instrument_ids": ["AAPL", ""]}
// after
{"external_order_instrument_ids": ["AAPL.NASDAQ"]}
Defensive patterns

Strategy: validation

Validate before calling

from nautilus_model.identifiers import InstrumentId
ids = [InstrumentId.from_str(s) for s in config.external_order_instrument_ids]

Type guard

def is_valid_instrument_id(s: str) -> bool:
    try:
        InstrumentId.from_str(s)
        return True
    except Exception:
        return False

Prevention

When it happens

Trigger: Passing a list entry to `external_order_instrument_ids` that lacks an exchange/venue suffix, contains whitespace, or is otherwise not a valid InstrumentId string when constructing a live node config.

Common situations: Typos in venue suffixes, using exchange codes like 'NASDAQ' instead of full 'AAPL.NASDAQ', empty strings left in the config list, or copying IDs from another system with a different ID format.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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