{"record":{"id":"0a72ede1341fa72b","repo":"nautechsystems/nautilus_trader","slug":"historical-binancebar-requests-require-external-ag-0a72ed","errorCode":null,"errorMessage":"historical BinanceBar requests require EXTERNAL aggregation","messagePattern":"historical BinanceBar requests require EXTERNAL aggregation","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/spot/data.rs","lineNumber":2258,"sourceCode":"                    }\n                }\n                Err(e) => log::error!(\"Instrument request failed: {e:?}\"),\n            }\n        });\n\n        Ok(())\n    }\n\n    fn request_data(&self, request: RequestCustomData) -> anyhow::Result<()> {\n        if request.data_type.type_name() != \"BinanceBar\" {\n            log::warn!(\n                \"Unsupported custom data request: {}\",\n                request.data_type.type_name()\n            );\n            return Ok(());\n        }\n        let bar_type = parse_binance_bar_type(&request.data_type)?;\n        anyhow::ensure!(\n            bar_type.aggregation_source() == AggregationSource::External,\n            \"historical BinanceBar requests require EXTERNAL aggregation\"\n        );\n        anyhow::ensure!(\n            bar_type.spec().price_type == PriceType::Last,\n            \"historical BinanceBar requests require LAST price type\"\n        );\n        anyhow::ensure!(\n            bar_type.spec().is_time_aggregated(),\n            \"historical BinanceBar requests require time aggregation\"\n        );\n        let http = self.http_client.clone();\n        let sender = self.data_sender.clone();\n        let request_id = request.request_id;\n        let client_id = request.client_id;\n        let data_type = request.data_type;\n        let start = request.start;\n        let end = request.end;","sourceCodeStart":2240,"sourceCodeEnd":2276,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/spot/data.rs#L2240-L2276","documentation":"Historical BinanceBar requests are fulfilled from Binance's REST kline API, which returns externally (exchange) aggregated bars. Requesting bars whose aggregation source is Internal (locally aggregated) cannot be served by request_data and is rejected with anyhow::ensure!.","triggerScenarios":"Calling request_data with a BinanceBar custom data type whose parsed bar_type.aggregation_source() is not AggregationSource::External, e.g. a bar type built with INTERNAL aggregation.","commonSituations":"Constructing bar types programmatically and forgetting to mark aggregation as external; reusing live-subscription bar types (internal aggregation) for historical requests.","solutions":["Build the bar type with AggregationSource::External for historical requests.","Use the dedicated historical/request API that constructs EXTERNAL bar types for Binance klines.","For internal aggregation, aggregate locally from streamed quotes/trades instead of requesting history."],"exampleFix":"// before\nlet bar_type = BarType::new(instrument_id, BarAggregation::Minute, PriceType::Last, AggregationSource::Internal);\n// after\nlet bar_type = BarType::new(instrument_id, BarAggregation::Minute, PriceType::Last, AggregationSource::External);","handlingStrategy":"validation","validationCode":"fn ensure_external_bars(bar_type: &BarType) -> Result<(), String> {\n    if bar_type.aggregation_source() == AggregationSource::External { Ok(()) }\n    else { Err(\"historical requests need EXTERNAL aggregation\".into()) }\n}","typeGuard":"fn is_external_bar_type(bar_type: &BarType) -> bool {\n    bar_type.aggregation_source() == AggregationSource::External\n}","tryCatchPattern":"if is_external_bar_type(&bar_type) {\n    client.request_data(request)?;\n} else {\n    log::warn!(\"skipping history request: internal bars not served by Binance REST\");\n}","preventionTips":["Always build bar types with AggregationSource::External for historical requests.","Separate live-subscription bar types from history-request bar types.","Add request-time validation in your request builder.","Note Binance klines are always exchange-aggregated."],"tags":["binance","bars","historical","validation"],"backgroundTag":"invalid-argument-value","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"}