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

  1. Fix the metadata value to a canonical InstrumentId string like "AAPL.NYSE" or "BTCUSDT.BINANCE"
  2. Validate the string with `InstrumentId::from_str` in a controlled context before storing it in metadata
  3. 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

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


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