{"record":{"id":"c1ed01f3a8ca1391","repo":"nautechsystems/nautilus_trader","slug":"either-start-date-time-or-duration-should-be-provi","errorCode":null,"errorMessage":"Either start_date_time or duration should be provided, not both","messagePattern":"Either start_date_time or duration should be provided, not both","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/historical/client.rs","lineNumber":237,"sourceCode":"    ///\n    /// # Errors\n    ///\n    /// Returns an error if the request fails.\n    #[allow(clippy::too_many_arguments)]\n    pub async fn request_bars(\n        &self,\n        bar_specifications: Vec<&str>,\n        end_date_time: Timestamp,\n        start_date_time: Option<Timestamp>,\n        duration: Option<&str>,\n        contracts: Option<Vec<Contract>>,\n        instrument_ids: Option<Vec<InstrumentId>>,\n        use_rth: bool,\n        timeout: u64,\n    ) -> anyhow::Result<Vec<Bar>> {\n        // Validate inputs\n        if start_date_time.is_some() && duration.is_some() {\n            anyhow::bail!(\"Either start_date_time or duration should be provided, not both\");\n        }\n\n        if let Some(start) = start_date_time\n            && start >= end_date_time\n        {\n            anyhow::bail!(\"Start date must be before end date\");\n        }\n\n        if let Some(duration) = duration {\n            duration.parse::<historical::Duration>().with_context(|| {\n                format!(\"duration must be in format: 'int S|D|W|M|Y', was '{duration}'\")\n            })?;\n        }\n\n        let contracts = contracts.unwrap_or_default();\n        let instrument_ids = instrument_ids.unwrap_or_default();\n\n        if contracts.is_empty() && instrument_ids.is_empty() {","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/historical/client.rs#L219-L255","documentation":"request_bars accepts either a start_date_time timestamp or an IB duration string (e.g. \"1 D\") to define the history window, but not both, because IB's historical data API itself takes one or the other. Providing both is ambiguous, so the client bails before contacting IB.","triggerScenarios":"Calling HistoricalClient::request_bars with Some(start_date_time) and Some(duration) simultaneously.","commonSituations":"Config-driven backfills where both a 'from' date and a lookback duration are configured; callers copying examples that use duration while also setting start in their wrapper; merging two call sites that each set a different option.","solutions":["Pass only start_date_time (with end_date_time) and set duration to None.","Pass only duration (e.g. \"1 D\") and leave start_date_time as None.","If both come from config, prefer start_date_time and drop the duration entry when it is present."],"exampleFix":"// before\nclient.request_bars(&[\"1-HOUR-LAST\"], end, Some(start), Some(\"1 D\"), None, Some(ids), true, 60).await?;\n// after\nclient.request_bars(&[\"1-HOUR-LAST\"], end, Some(start), None, None, Some(ids), true, 60).await?;","handlingStrategy":"validation","validationCode":"if start.is_some() && duration.is_some() {\n    return Err(\"pass either start_date_time or duration, not both\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Model the window as an enum (Start(Timestamp) | Duration(String)) in your config so exclusivity is enforced by types.","Never pass duration from a wrapper that already computes start from duration."],"tags":["mutually-exclusive-arguments","rust","validation","historical-data"],"backgroundTag":"mutually-exclusive-options","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"}