{"record":{"id":"0831262b9eb3e589","repo":"nautechsystems/nautilus_trader","slug":"only-external-aggregation-is-supported-083126","errorCode":null,"errorMessage":"Only EXTERNAL aggregation is supported","messagePattern":"Only EXTERNAL aggregation is supported","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/http/client.rs","lineNumber":3544,"sourceCode":"        &self,\n        bar_type: BarType,\n        start: Option<Timestamp>,\n        mut end: Option<Timestamp>,\n        limit: Option<u32>,\n    ) -> anyhow::Result<Vec<Bar>> {\n        const HISTORY_SPLIT_DAYS: i64 = 100;\n        const MAX_PAGES_SOFT: usize = 500;\n\n        #[derive(Clone, Copy, Debug, PartialEq, Eq)]\n        enum Mode {\n            Latest,\n            Backward,\n            Range,\n        }\n\n        let limit = if limit == Some(0) { None } else { limit };\n\n        anyhow::ensure!(\n            bar_type.aggregation_source() == AggregationSource::External,\n            \"Only EXTERNAL aggregation is supported\"\n        );\n\n        if let (Some(s), Some(e)) = (start, end) {\n            anyhow::ensure!(s < e, \"Invalid time range: start={s:?} end={e:?}\");\n        }\n\n        let now = self.inner.clock.get_time_ns().to_datetime_utc();\n\n        if let Some(s) = start\n            && s > now\n        {\n            return Ok(Vec::new());\n        }\n\n        if let Some(e) = end\n            && e > now","sourceCodeStart":3526,"sourceCodeEnd":3562,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/http/client.rs#L3526-L3562","documentation":"OKX HTTP client request for historical bars (candles) requires the bar_type's aggregation source to be EXTERNAL, meaning the raw OKX candles are used directly rather than internally aggregated ticks. Internal (self-aggregated) bar sources are not implemented in this adapter, so the request is rejected with anyhow::ensure! before any HTTP call.","triggerScenarios":"Calling request_bars / historical candle fetch with a BarType whose AggregationSource is Internal, e.g. a bar type constructed via BarType::new(instrument_id, spec, AggregationSource::Internal).","commonSituations":"Configuring a strategy with internally aggregated bars and passing them to the OKX data client; copying bar_type definitions from another adapter that supports internal aggregation; default aggregation source left at Internal when building the BarType.","solutions":["Pass a BarType created with AggregationSource::External","Configure the strategy's bar types to use external aggregation for the OKX adapter","If internal aggregation is required, subscribe to raw external bars via OKX and aggregate them in a separate aggregator component"],"exampleFix":"// before\nlet bar_type = BarType::new(instrument_id, bar_spec, AggregationSource::Internal);\n// after\nlet bar_type = BarType::new(instrument_id, bar_spec, AggregationSource::External);","handlingStrategy":"validation","validationCode":"fn ensure_external(bar_type: &BarType) -> Result<(), String> {\n    if bar_type.aggregation_source() == AggregationSource::External { Ok(()) }\n    else { Err(format!(\"bar_type {} must use EXTERNAL aggregation for OKX\", bar_type)) }\n}","typeGuard":"fn is_external(bar_type: &BarType) -> bool {\n    bar_type.aggregation_source() == AggregationSource::External\n}","tryCatchPattern":null,"preventionTips":["Always construct OKX bar types with AggregationSource::External","Centralize bar-type creation in a helper that enforces external source","Document in strategy config that OKX does not support internal aggregation"],"tags":["okx","bars","aggregation","validation"],"backgroundTag":"unsupported-operation","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"}