nautechsystems/nautilus_trader · error

AccountId contains '-'

Error message

AccountId contains '-'

What it means

`AccountId::get_issuer` extracts the venue prefix of an account ID of the form `ISSUER-NUMBER` (e.g. `SIM-001`). It panics with "AccountId contains '-'" when the internal string contains no hyphen, meaning the ID was constructed bypassing validation (via `from_str_unchecked` or raw/new constructors) or the format contract changed. Well-formed AccountIds validated through the parser always contain a hyphen.

Source

Thrown at crates/model/src/identifiers/account_id.rs:115

    #[must_use]
    pub fn inner(&self) -> Ustr {
        self.0
    }

    /// Returns the inner identifier value as a string slice.
    #[must_use]
    pub fn as_str(&self) -> &str {
        self.0.as_str()
    }

    /// Returns the account issuer for this identifier.
    ///
    /// # Panics
    ///
    /// Panics if the internal ID does not contain a hyphen separator.
    #[must_use]
    pub fn get_issuer(&self) -> Venue {
        Venue::from_str_unchecked(self.0.split_once('-').expect("AccountId contains '-'").0)
    }

    /// Returns the account ID assigned by the issuer.
    ///
    /// # Panics
    ///
    /// Panics if the internal ID does not contain a hyphen separator.
    #[must_use]
    pub fn get_issuers_id(&self) -> &str {
        self.0.split_once('-').expect("AccountId contains '-'").1
    }
}

impl Debug for AccountId {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "\"{}\"", self.0)
    }
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Fix the account ID string so it includes the issuer hyphen separator, e.g. "BINANCE-001".
  2. Construct AccountId via the checked `from_str`/parser path so malformed IDs are rejected at creation instead of panicking later.
  3. Audit where the ID originates (config, database, adapter) and correct the formatting there.
  4. If you must inspect arbitrary strings, split on '-' yourself and handle None instead of using get_issuer.

Example fix

// before
let id = AccountId::new("SIM001");
let issuer = id.get_issuer(); // panics
// after
let id = AccountId::from_str("SIM-001").expect("valid account id");
let issuer = id.get_issuer(); // Venue("SIM")
Defensive patterns

Strategy: validation

Validate before calling

// Rust caller
fn safe_issuer(id: &AccountId) -> Option<Venue> {
    id.as_str().split_once('-').map(|(issuer, _)| Venue::from_str_unchecked(issuer))
}

Type guard

fn is_well_formed_account_id(s: &str) -> bool {
    s.split_once('-').map_or(false, |(issuer, num)| !issuer.is_empty() && !num.is_empty())
}

Try / catch

// AccountId methods panic rather than return Result; validate first
if is_well_formed_account_id(id.as_str()) {
    let issuer = id.get_issuer();
} else {
    log::error!("malformed account id: {}", id);
}

Prevention

When it happens

Trigger: Calling get_issuer() on an AccountId built with `AccountId::new`/unsafe unchecked constructors from a string lacking a hyphen, e.g. "SIM001" instead of "SIM-001".

Common situations: Deserializing account IDs from external config/CSV/databases with a different naming convention, hand-crafted IDs in tests, or upstream venue renames dropping the separator.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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