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
- Build the InstrumentId from the Polymarket instrument definition so the symbol keeps the {condition_id}-{token_id} form.
- Check symbol.contains('-') before calling extract_token_id.
- 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
- Never strip the -{token_id} suffix when manipulating symbols.
- Derive InstrumentIds from the instrument factory rather than string concatenation by hand.
- Add a guard that skips non-Polymarket-shaped symbols in subscription bookkeeping.
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
- Cannot extract condition_id from symbol '{symbol}': no '-' s
- invalid signed E18 integer for {field}: {value}
- Empty book snapshot for {instrument_id}
- Failed to parse clob_token_ids '{}': {e}
- Failed to parse outcomes '{}': {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ca14ea4c57455dae.
Report an issue: GitHub.