{"record":{"id":"a71ea990b21e600e","repo":"nautechsystems/nautilus_trader","slug":"leg-instrument-not-found-in-contract-details-af","errorCode":null,"errorMessage":"Leg instrument {} not found in contract details after loading","messagePattern":"Leg instrument (.+?) not found in contract details after loading","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/providers/instruments.rs","lineNumber":1304,"sourceCode":"            );\n\n            // Load the individual leg instrument\n            self.fetch_contract_details(\n                client,\n                *leg_instrument_id,\n                force_instrument_update,\n                filters.clone(),\n            )\n            .await\n            .with_context(|| format!(\"Failed to load leg instrument: {}\", leg_instrument_id))?;\n\n            // Get the contract details for this leg\n            let leg_details = self\n                .contract_details\n                .get(leg_instrument_id)\n                .map(|entry| entry.value().clone())\n                .ok_or_else(|| {\n                    anyhow::anyhow!(\n                        \"Leg instrument {} not found in contract details after loading\",\n                        leg_instrument_id\n                    )\n                })?;\n\n            leg_contract_details.push((leg_details, *ratio));\n        }\n\n        // Create the spread instrument\n        let timestamp = nautilus_core::time::get_atomic_clock_realtime().get_time_ns();\n        let leg_details_refs: Vec<(&ibapi::contracts::ContractDetails, i32)> =\n            leg_contract_details.iter().map(|(d, r)| (d, *r)).collect();\n\n        let bag_contract = self.create_bag_contract_from_legs(\n            &leg_contract_details,\n            Some(spread_instrument_id),\n            None,\n        )?;","sourceCodeStart":1286,"sourceCodeEnd":1322,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/providers/instruments.rs#L1286-L1322","documentation":"fetch_spread_instrument looks up each combo leg's ContractDetails in the provider's contract_details cache by leg InstrumentId. This error means a required leg was not present in the cache after the provider attempted to load it, so the spread cannot be assembled.","triggerScenarios":"Calling resolve_contract_for_instrument_async / load_with_return_async / load_ids_async for a spread whose leg instrument_id has no entry in self.contract_details after load — e.g. the leg load request returned no matching contract for that symbol/exchange/currency.","commonSituations":"Leg symbol misspelled or with wrong venue/currency so IB returns no details; leg never individually subscribed/loaded before the spread fetch; IB API returned an empty contract details list for the leg and the cache write was skipped.","solutions":["Load each leg instrument individually (load_ids_async per leg) and confirm the load succeeds before fetching the spread","Verify the leg symbol, venue (exchange), and currency exactly match a tradable IB contract","Check that the leg load path actually inserts into contract_details (look for early returns on empty IB results)","Retry after the async load completes — the error can occur if the spread is fetched before leg loads finish"],"exampleFix":"// before\nself.fetch_spread_instrument(instrument, leg_ids).await?;\n// after\nfor leg in leg_ids {\n    self.load_ids_async(&[leg.clone()], None).await?;\n}\nself.fetch_spread_instrument(instrument, leg_ids).await?;","handlingStrategy":"validation","validationCode":"if provider.contract_details.get(&leg_id).is_none() {\n    provider.load_ids_async(&[leg_id.clone()], None).await?;\n}","typeGuard":"fn is_leg_cached(provider: &IbInstrumentsProvider, id: &InstrumentId) -> bool {\n    provider.contract_details.get(id).is_some()\n}","tryCatchPattern":"match fetch_spread_instrument(...).await {\n    Ok(i) => Ok(i),\n    Err(e) if e.to_string().contains(\"not found in contract details\") =>\n        Err(SpreadError::LegMissing(e.to_string())),\n    Err(e) => Err(e.into()),\n}","preventionTips":["Verify leg symbol/venue/currency resolve to a real IB contract before spread fetch","Await all leg loads to completion before fetching the spread","Log the set of cached leg ids when a spread fetch fails to spot missing legs"],"tags":["rust","interactive-brokers","cache-miss","spread"],"backgroundTag":"entity-not-found","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}