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
- Fix the offending instrument ID string to a valid InstrumentId format `SYMBOL.VENUE` (e.g. 'BTCUSDT.BINANCE')
- Remove empty or whitespace-only strings from the list
- 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
- Always use SYMBOL.VENUE format for instrument IDs
- Validate config lists with InstrumentId.from_str at startup
- Strip empty/whitespace entries before passing lists to the node
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
- {FAILED}: {e}
- Binance v2 does not support instrument filter_callable {filt
- default_leverage requires spot_account_type=Margin
- Kraken Spot does not support the demo environment
- Cannot expand parent subscription for {instrument_id}: symbo
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/41b00aef2f1b446f.
Report an issue: GitHub.