{"record":{"id":"789b7aa29fba6d52","repo":"nautechsystems/nautilus_trader","slug":"either-instrument-ids-or-contracts-must-be-provide","errorCode":null,"errorMessage":"Either instrument_ids or contracts must be provided","messagePattern":"Either instrument_ids or contracts must be provided","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/historical/client.rs","lineNumber":849,"sourceCode":"    /// * `contracts` - Optional list of IB contracts\n    ///\n    /// # Returns\n    ///\n    /// Returns a list of instruments.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if loading fails.\n    pub async fn request_instruments(\n        &self,\n        instrument_ids: Option<Vec<InstrumentId>>,\n        contracts: Option<Vec<Contract>>,\n    ) -> anyhow::Result<Vec<InstrumentAny>> {\n        let instrument_ids = instrument_ids.unwrap_or_default();\n        let contracts = contracts.unwrap_or_default();\n\n        if instrument_ids.is_empty() && contracts.is_empty() {\n            anyhow::bail!(\"Either instrument_ids or contracts must be provided\");\n        }\n\n        let loaded_ids = self\n            .instrument_provider\n            .load_ids_with_return_async(&self.ib_client, instrument_ids, None)\n            .await?;\n        let mut loaded_instruments = self.instrument_provider.find_all(&loaded_ids);\n\n        // Load instruments from contracts (equivalent to Python's _fetch_instruments_if_not_cached)\n        for contract in contracts {\n            match self\n                .instrument_provider\n                .get_instrument(&self.ib_client, &contract)\n                .await\n            {\n                Ok(Some(instrument)) => {\n                    if !loaded_instruments.iter().any(|i| i.id() == instrument.id()) {\n                        loaded_instruments.push(instrument);","sourceCodeStart":831,"sourceCodeEnd":867,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/historical/client.rs#L831-L867","documentation":"request_instruments requires either Nautilus InstrumentIds or IB Contracts to know which instruments to load. If both lists are empty after unwrap_or_default, there is nothing to resolve and the client bails.","triggerScenarios":"Calling request_instruments with instrument_ids=None/[] and contracts=None/[].","commonSituations":"Passing None for both when intending 'load everything' (not supported); empty config-driven instrument universe; wrappers that filter ids before calling and end up with none.","solutions":["Pass at least one InstrumentId in instrument_ids.","Or pass a non-empty Vec<Contract> when you already hold IB contract definitions.","Populate the instrument universe config/subscription that produced the empty list."],"exampleFix":"// before\nclient.request_instruments(None, None).await?;\n// after\nlet ids = vec![InstrumentId::from(\"ESZ6.CME\")];\nclient.request_instruments(Some(ids), None).await?;","handlingStrategy":"validation","validationCode":"if instrument_ids.as_ref().map_or(true, |i| i.is_empty())\n    && contracts.as_ref().map_or(true, |c| c.is_empty()) {\n    return Err(\"request_instruments needs ids or contracts\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not pass None for both arguments expecting a bulk load; the client requires an explicit list.","Validate the instrument universe before calling.","Use load_ids_with_return_async directly when you need catalog-wide loading semantics."],"tags":["missing-argument","validation","rust","instruments"],"backgroundTag":"missing-required-argument","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"}