nautechsystems/nautilus_trader · error · anyhow::Error

Cannot extract token_id from symbol '{symbol}': no '-' separ

Error message

Cannot extract token_id from symbol '{symbol}': no '-' separator

What it means

extract_token_id splits the symbol at the last '-' via rsplit_once and returns the trailing token id. Since Polymarket symbols are {condition_id}-{token_id}, a symbol without any '-' cannot yield a token id and triggers this error.

Source

Thrown at crates/adapters/polymarket/src/providers.rs:605

    symbol
        .rfind('-')
        .map(|idx| symbol[..idx].to_string())
        .ok_or_else(|| {
            anyhow::anyhow!("Cannot extract condition_id from symbol '{symbol}': no '-' separator")
        })
}

/// Extracts the token ID from an instrument symbol.
///
/// Polymarket instrument symbols follow the pattern `{condition_id}-{token_id}`. This extracts the
/// token_id by splitting at the last `-`.
pub(crate) fn extract_token_id(instrument_id: &InstrumentId) -> anyhow::Result<String> {
    let symbol = instrument_id.symbol.as_str();
    symbol
        .rsplit_once('-')
        .map(|(_, token_id)| token_id.to_string())
        .ok_or_else(|| {
            anyhow::anyhow!("Cannot extract token_id from symbol '{symbol}': no '-' separator")
        })
}

/// Builds validated market keyset parameters from string key/value filters.
///
/// # Errors
///
/// Returns an error for unknown keys, malformed values, or invalid filter combinations.
pub fn build_gamma_params_from_hashmap(
    map: &HashMap<String, String>,
) -> anyhow::Result<GetGammaMarketsParams> {
    for key in map.keys() {
        match key.as_str() {
            "is_active"
            | "active"
            | "closed"
            | "archived"
            | "id"

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Build the InstrumentId from the Polymarket instrument definition so the symbol keeps the {condition_id}-{token_id} form.
  2. Check symbol.contains('-') before calling extract_token_id.
  3. Trace the InstrumentId's origin — likely a non-Polymarket instrument reached provider code.

Example fix

// before
let token_id = extract_token_id(&instrument_id)?;
// after
let symbol = instrument_id.symbol.as_str();
let token_id = match symbol.rsplit_once('-') {
    Some((_, tid)) => tid.to_string(),
    None => return Ok(()), // not a Polymarket instrument; skip
};
Defensive patterns

Strategy: type-guard

Validate before calling

fn symbol_has_token_id(instrument_id: &InstrumentId) -> bool {
    instrument_id.symbol.as_str().rsplit_once('-').map_or(false, |(_, t)| !t.is_empty())
}

Type guard

fn polymarket_token_id(instrument_id: &InstrumentId) -> Option<String> {
    instrument_id.symbol.as_str().rsplit_once('-').map(|(_, t)| t.to_string())
}

Try / catch

match extract_token_id(&instrument_id) {
    Ok(tid) => tid,
    Err(e) => { debug!("skipping non-Polymarket symbol: {e}"); return Ok(()); }
}

Prevention

When it happens

Trigger: Calling extract_token_id with an InstrumentId whose symbol has no '-' separator — e.g. a raw condition_id without a token suffix, or a symbol created outside the Polymarket factory.

Common situations: Constructing instrument ids by hand in tests or scripts, mixing venues' instrument ids, or stripping the token suffix accidentally with string manipulation.

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/ca14ea4c57455dae. Report an issue: GitHub.