nautechsystems/nautilus_trader · error
Cannot extract market ID from {instrument_id}
Error message
Cannot extract market ID from {instrument_id} What it means
Betfair instrument symbols encode both a market and a runner: {market_id}-{selection_id} or {market_id}-{selection_id}-{handicap} (e.g. 1.246503964-12345-0.5). extract_market_id splits the symbol on '-' and takes the first segment; with fewer than 2 segments there is no separator and the market id cannot be extracted, so it bails. This runs on execution paths (submit/cancel) and data/provider lookups.
Source
Thrown at crates/adapters/betfair/src/common/parse.rs:507
)
.with_info(info))
}
/// Extracts the Betfair market ID from a Nautilus instrument ID.
///
/// Instrument IDs follow the format `{market_id}-{selection_id}.BETFAIR`
/// or `{market_id}-{selection_id}-{handicap}.BETFAIR`.
///
/// # Errors
///
/// Returns an error if the symbol does not contain a hyphen separator.
pub fn extract_market_id(instrument_id: &InstrumentId) -> anyhow::Result<String> {
let symbol = instrument_id.symbol.as_str();
let parts: Vec<&str> = symbol.splitn(3, '-').collect();
if parts.len() >= 2 {
Ok(parts[0].to_string())
} else {
anyhow::bail!("Cannot extract market ID from {instrument_id}")
}
}
/// Extracts the selection ID and handicap from a Nautilus instrument ID.
///
/// # Errors
///
/// Returns an error if the symbol cannot be parsed into the expected format.
pub fn extract_selection_id(
instrument_id: &InstrumentId,
) -> anyhow::Result<(SelectionId, Decimal)> {
let symbol = instrument_id.symbol.as_str();
let parts: Vec<&str> = symbol.splitn(3, '-').collect();
if parts.len() < 2 {
anyhow::bail!("Cannot extract selection ID from {instrument_id}");
}
let selection_id: SelectionId = parts[1]View on GitHub (pinned to a4b06ed870)
Solutions
- Always construct ids via make_instrument_id(market_id, selection_id, handicap) instead of string concatenation
- If you only hold a market id, it is not an instrument — resolve selections from the market catalogue first, then build the id
- Validate the symbol format (>= 2 hyphen-separated parts) before sending orders or data requests
- Check the instrument's venue is BETFAIR and the symbol was not truncated by config/env parsing
Example fix
// before
let id = InstrumentId::from("1.246503964.BETFAIR"); // bare market id — no selection
// after
let id = make_instrument_id("1.246503964", 12345, Decimal::ZERO); Defensive patterns
Strategy: validation
Validate before calling
// Validate Betfair instrument id shape before calling execution/data APIs
fn is_valid_betfair_instrument_id(id: &InstrumentId) -> bool {
if id.venue.as_str() != "BETFAIR" {
return false;
}
let parts: Vec<&str> = id.symbol.as_str().splitn(3, '-').collect();
parts.len() >= 2
&& parts[0].split('.').count() == 2 // market id like 1.246503964
&& parts[1].parse::<u64>().is_ok()
&& (parts.len() == 2 || parts[2].parse::<Decimal>().is_ok())
}
if !is_valid_betfair_instrument_id(&instrument_id) {
anyhow::bail!("refusing order for malformed Betfair instrument {instrument_id}");
} Try / catch
match extract_market_id(&instrument_id) {
Ok(market_id) => submit_order(market_id, /* ... */).await,
Err(e) => {
log::error!("rejecting order for unparseable instrument {instrument_id}: {e}");
// do not send; surface to strategy as a rejected command
Err(e)
}
} Prevention
- Never build Betfair instrument ids by string concatenation — use make_instrument_id(market_id, selection_id, handicap)
- Remember a Betfair market id (1.xxxxx) alone is not an instrument; it must pair with a selection id
- Validate instrument ids at strategy config load time, not at order-send time
When it happens
Trigger: An InstrumentId built from a bare Betfair market id like 1.246503964 (no -selection suffix); passing an instrument from another venue or a hand-assembled symbol into betfair execution or data requests; stripping the selection component during config or mapping.
Common situations: Users confuse Betfair market ids (dot-separated, 1.xxxxx) with Nautilus instrument ids; strategies subscribe to instruments by market catalogue but orders reference a market id string; symbols mangled by config templating or string transforms that drop hyphens.
Related errors
- Cannot extract selection ID from {instrument_id}
- height must be positive, was {self.height}
- pandas is required for report generation; install it with `p
- pandas is required for visualization; install it with `pip i
- {name} must not be None
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/29985f6e2062b358.
Report an issue: GitHub.