nautechsystems/nautilus_trader · error
Invalid `InstrumentId` for 'instrument_id'
Error message
Invalid `InstrumentId` for 'instrument_id'
What it means
In `Data::instrument_id`, the metadata dict's "instrument_id" string is parsed into an `InstrumentId`, and parsing failure panics with "Invalid `InstrumentId` for 'instrument_id'". The library treats metadata as already validated, so a malformed ID (missing venue, bad characters) is a hard error. Note the method returns `Option` when the key is absent — this panic only fires when the key exists but the value is unparseable.
Source
Thrown at crates/model/src/data/mod.rs:899
/// Returns the optional catalog path identifier (can contain subdirs, e.g. `"venue//symbol"`).
#[must_use]
pub fn identifier(&self) -> Option<&str> {
self.identifier.as_deref()
}
/// Returns an [`Option<InstrumentId>`] parsed from the metadata.
///
/// # Panics
///
/// This function panics if:
/// - The `instrument_id` value contained in the metadata is invalid.
#[must_use]
pub fn instrument_id(&self) -> Option<InstrumentId> {
let metadata = self.metadata.as_ref()?;
let instrument_id = metadata.get_str("instrument_id")?;
Some(
InstrumentId::from_str(instrument_id)
.expect("Invalid `InstrumentId` for 'instrument_id'"),
)
}
/// Returns an [`Option<Venue>`] parsed from the metadata.
///
/// # Panics
///
/// This function panics if:
/// - The `venue` value contained in the metadata is invalid.
#[must_use]
pub fn venue(&self) -> Option<Venue> {
let metadata = self.metadata.as_ref()?;
let venue_str = metadata.get_str("venue")?;
Some(Venue::from(venue_str))
}
/// Returns an [`Option<UnixNanos>`] parsed from the metadata `start` field.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Fix the metadata value to a canonical InstrumentId string like "AAPL.NYSE" or "BTCUSDT.BINANCE"
- Validate the string with `InstrumentId::from_str` in a controlled context before storing it in metadata
- If migrating old data, re-write metadata with the correct format
Example fix
// before metadata["instrument_id"] = "AAPL" // missing venue // after metadata["instrument_id"] = "AAPL.NYSE" // valid InstrumentId format SYMBOL.VENUE
Defensive patterns
Strategy: validation
Validate before calling
from nautilus_trader.model.identifiers import InstrumentId
def validate_instrument_id_metadata(metadata: dict) -> str:
raw = metadata.get("instrument_id")
if raw is not None:
InstrumentId.from_str(raw) # raises a controlled error if invalid
return raw Type guard
import re
_INSTRUMENT_ID_RE = re.compile(r"^[A-Za-z0-9._\-]+\.[A-Za-z0-9._\-]+$")
def is_instrument_id_str(s: str) -> bool:
return bool(_INSTRUMENT_ID_RE.match(s)) Try / catch
try:
instrument_id = data.instrument_id()
except Exception as e:
logger.error(f"malformed instrument_id in metadata: {metadata.get('instrument_id')!r}")
raise Prevention
- Always write InstrumentId in SYMBOL.VENUE canonical format
- Validate IDs via InstrumentId.from_str before storing in metadata
- Check persisted/migrated data for legacy ID formats
When it happens
Trigger: Creating a `Data`/custom data payload whose metadata contains `instrument_id` as a string that is not a valid `InstrumentId` (e.g. "AAPL" without a venue, "AAPL@" or extra whitespace), then calling `.instrument_id()`.
Common situations: Hand-written metadata in custom data classes from Python; config files or adapters writing IDs in a non-canonical format; old persisted data written by a version with different ID formatting.
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}
- Invalid `UnixNanos` for 'start'
- Invalid `UnixNanos` for 'end'
- Invalid `usize` for 'limit'
- Invalid scientific notation exponent '{exponent}': must be a
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/797b1d1d4c9434a4.
Report an issue: GitHub.