{"record":{"id":"41b00aef2f1b446f","repo":"nautechsystems/nautilus_trader","slug":"invalid-external-order-instrument-ids-instrument","errorCode":null,"errorMessage":"Invalid `external_order_instrument_ids` instrument ID {claim}: {e}","messagePattern":"Invalid `external_order_instrument_ids` instrument ID (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/live/src/python/node.rs","lineNumber":1916,"sourceCode":"        return Ok(None);\n    };\n\n    if claims.is_none() {\n        return Ok(None);\n    }\n\n    if let Ok(claims) = claims.extract::<Vec<InstrumentId>>() {\n        return Ok(Some(claims));\n    }\n\n    let claim_strings = claims\n        .extract::<Vec<String>>()\n        .map_err(|e| anyhow::anyhow!(\"Invalid `external_order_instrument_ids` type: {e}\"))?;\n    let claims = claim_strings\n        .into_iter()\n        .map(|claim| {\n            InstrumentId::from_str(&claim).map_err(|e| {\n                anyhow::anyhow!(\n                    \"Invalid `external_order_instrument_ids` instrument ID {claim}: {e}\"\n                )\n            })\n        })\n        .collect::<anyhow::Result<Vec<_>>>()?;\n\n    Ok(Some(claims))\n}\n\n#[cfg(feature = \"examples\")]\ntype BuiltinActorRegister = for<'py> fn(&mut LiveNode, &Bound<'py, PyAny>) -> PyResult<()>;\n\n#[cfg(feature = \"examples\")]\ntype BuiltinStrategyRegister = for<'py> fn(&mut LiveNode, &Bound<'py, PyAny>) -> PyResult<()>;\n\n#[cfg(feature = \"examples\")]\nfn builtin_actor_register(type_name: &str) -> Option<BuiltinActorRegister> {\n    match type_name {","sourceCodeStart":1898,"sourceCodeEnd":1934,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/python/node.rs#L1898-L1934","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n{\"external_order_instrument_ids\": [\"AAPL\", \"\"]}\n// after\n{\"external_order_instrument_ids\": [\"AAPL.NASDAQ\"]}","handlingStrategy":"validation","validationCode":"from nautilus_model.identifiers import InstrumentId\nids = [InstrumentId.from_str(s) for s in config.external_order_instrument_ids]","typeGuard":"def is_valid_instrument_id(s: str) -> bool:\n    try:\n        InstrumentId.from_str(s)\n        return True\n    except Exception:\n        return False","tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","instrument-id","config-validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}