{"record":{"id":"4bb23f2039096820","repo":"nautechsystems/nautilus_trader","slug":"cannot-extract-selection-id-from-instrument-id","errorCode":null,"errorMessage":"Cannot extract selection ID from {instrument_id}","messagePattern":"Cannot extract selection ID from (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/betfair/src/common/parse.rs","lineNumber":508,"sourceCode":"    if parts.len() >= 2 {\n        Ok(parts[0].to_string())\n    } else {\n        anyhow::bail!(\"Cannot extract market ID from {instrument_id}\")\n    }\n}\n\n/// Extracts the selection ID and handicap from a Nautilus instrument ID.\n///\n/// # Errors\n///\n/// Returns an error if the symbol cannot be parsed into the expected format.\npub fn extract_selection_id(\n    instrument_id: &InstrumentId,\n) -> anyhow::Result<(SelectionId, Decimal)> {\n    let symbol = instrument_id.symbol.as_str();\n    let parts: Vec<&str> = symbol.splitn(3, '-').collect();\n    if parts.len() < 2 {\n        anyhow::bail!(\"Cannot extract selection ID from {instrument_id}\");\n    }\n\n    let selection_id: SelectionId = parts[1]\n        .parse()\n        .with_context(|| format!(\"invalid selection ID in {instrument_id}\"))?;\n\n    let handicap = if parts.len() == 3 {\n        parts[2]\n            .parse::<Decimal>()\n            .with_context(|| format!(\"invalid handicap in {instrument_id}\"))?\n    } else {\n        Decimal::ZERO\n    };\n\n    Ok((selection_id, handicap))\n}\n\n#[cfg(test)]","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/betfair/src/common/parse.rs#L490-L526","documentation":"extract_selection_id splits the Betfair instrument symbol on '-' and expects the second part to be the numeric selection ID. If the symbol has fewer than two parts, or the second part fails to parse as a SelectionId (with a 'invalid selection ID' context), this error is raised.","triggerScenarios":"Calling extract_selection_id (directly or via submit_order/submit_order_list) with a symbol lacking a '-'-separated selection part, or where the part after the first '-' is not a valid number, e.g. '1.23456789-ABC'.","commonSituations":"Malformed hand-built instrument IDs; using the market ID twice ('1.23456789-1.23456789' parse failure path); symbols reordered or truncated.","solutions":["Use symbol format '<marketId>-<selectionId>[-<handicap>]' with a numeric selection ID","Verify the selection ID matches the Betfair runner ID from the market catalog","Pre-validate with extract_market_id and parse the selection part as an integer before constructing the instrument"],"exampleFix":"// before\nlet id = InstrumentId::from(\"BETFAIR.1.23456789-runner\");\n// after\nlet id = InstrumentId::from(\"BETFAIR.1.23456789-12345\");","handlingStrategy":"validation","validationCode":"fn valid_selection_part(symbol: &str) -> bool {\n    symbol.splitn(3, '-').nth(1).map_or(false, |s| s.parse::<u64>().is_ok())\n}","typeGuard":"fn as_betfair_selection(id: &InstrumentId) -> Option<(SelectionId, Decimal)> {\n    extract_selection_id(id).ok()\n}","tryCatchPattern":"match extract_selection_id(&instrument_id) {\n    Ok((selection_id, handicap)) => submit(selection_id, handicap),\n    Err(e) => { log::error!(\"invalid Betfair selection in {instrument_id}: {e}\"); Err(e) }\n}","preventionTips":["Verify selection IDs are numeric Betfair runner IDs from the market catalog","Parse the selection part as an integer when constructing instrument IDs","Unit-test symbol round-tripping (market + selection + handicap) for your strategy"],"tags":["betfair","instrument-id","parsing"],"backgroundTag":"invalid-identifier-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}