nautechsystems/nautilus_trader · error
Invalid `external_order_instrument_ids` type: {e}
Error message
Invalid `external_order_instrument_ids` type: {e} What it means
Raised while extracting the external_order_instrument_ids attribute from a strategy config: the value is neither a list of InstrumentId objects nor a list of strings parseable as InstrumentId. The node accepts both forms and rejects anything else.
Source
Thrown at crates/live/src/python/node.rs:1911
fn extract_external_order_instrument_ids_config_attr(
config_obj: &Bound<'_, PyAny>,
) -> anyhow::Result<Option<Vec<InstrumentId>>> {
let Ok(claims) = config_obj.getattr("external_order_instrument_ids") else {
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")]View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the value is a list, e.g. ["AAPL.NASDAQ", "MSFT.NASDAQ"]
- Use fully qualified instrument IDs with venue (InstrumentId::from_str parses venue.symbol); fix IDs flagged by the follow-up 'instrument ID' error
- In Python configs pass list(instrument_ids), not a tuple or single string
- Validate IDs up front with InstrumentId.from_str in a sanity check before launching the node
Example fix
// before config["external_order_instrument_ids"] = "AAPL.NASDAQ,MSFT.NASDAQ" // after config["external_order_instrument_ids"] = ["AAPL.NASDAQ", "MSFT.NASDAQ"]
Defensive patterns
Strategy: validation
Validate before calling
from nautilus_trader.model.identifiers import InstrumentId ids = config["external_order_instrument_ids"] assert isinstance(ids, list), "must be a list" parsed = [InstrumentId.from_str(i) for i in ids] # raises on bad IDs
Type guard
def valid_external_ids(value) -> bool:
from nautilus_trader.model.identifiers import InstrumentId
if not isinstance(value, list):
return False
try:
[InstrumentId.from_str(i) for i in value]
return True
except Exception:
return False Try / catch
try:
node.add_strategy_from_config(cfg)
except Exception as e:
if "external_order_instrument_ids" in str(e):
raise ValueError("external_order_instrument_ids must be a list of 'SYMBOL.VENUE' strings") from e
raise Prevention
- Always pass a list of fully qualified 'SYMBOL.VENUE' strings
- Never pass a single comma-joined string or a tuple
- Validate IDs with InstrumentId.from_str before configuring the node
When it happens
Trigger: Setting external_order_instrument_ids in the strategy config to a wrong shape: a single string instead of a list, a list of non-instrument strings (typos like 'AAPL' without venue, or 'EUR/USD' when venue format is required), a set, tuple, or None-adjacent non-list type.
Common situations: Hand-editing YAML/JSON configs with a comma-joined string; missing the venue suffix ("AAPL" instead of "AAPL.NASDAQ"); passing a tuple from Python code where a list is expected by the extractor.
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
- Invalid `external_order_claims` type: {e}
- Invalid `external_order_claims` instrument ID {claim}: {e}
- Invalid `actor_id` type
- Invalid `exec_algorithm_id`/`actor_id` type
- Invalid config type for BinanceDataClientFactory. Expected B
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4b50d09dcb616045.
Report an issue: GitHub.