nautechsystems/nautilus_trader · error · anyhow::Error
Binance historical bars require LAST price type
Error message
Binance historical bars require LAST price type
What it means
The standard historical-bars request path only serves LAST-price bars: after the EXTERNAL aggregation check it enforces `PriceType::Last`. Binance klines are last-trade candles, so MID/BID/ASK bar types are rejected before the HTTP fetch is spawned.
Source
Thrown at crates/adapters/binance/src/futures/data.rs:3006
fn request_bars(&self, request: RequestBars) -> anyhow::Result<()> {
let http = self.http_client.clone();
let sender = self.data_sender.clone();
let bar_type = request.bar_type;
let start = request.start;
let end = request.end;
let limit = request.limit.map(|n| n.get() as u32);
let request_id = request.request_id;
let client_id = request.client_id.unwrap_or(self.client_id);
let params = request.params;
let clock = self.clock;
let start_nanos = datetime_to_unix_nanos(start);
let end_nanos = datetime_to_unix_nanos(end);
anyhow::ensure!(
bar_type.aggregation_source() == AggregationSource::External,
"Binance historical bars require EXTERNAL aggregation"
);
anyhow::ensure!(
bar_type.spec().price_type == PriceType::Last,
"Binance historical bars require LAST price type"
);
anyhow::ensure!(
bar_type.spec().is_time_aggregated(),
"Binance historical bars require time aggregation"
);
get_runtime().spawn(async move {
let result = http.request_bars(bar_type, start, end, limit).await;
match result.context("failed to request bars from Binance Futures") {
Ok(bars) => {
let response = DataResponse::Bars(BarsResponse::new(
request_id,
client_id,
bar_type,
bars,View on GitHub (pinned to a4b06ed870)
Solutions
- Request a LAST bar type, e.g. `BTCUSDT-PERP.BINANCE-1-MINUTE-LAST-EXTERNAL`
- For quote-price bars, collect book/quote data and aggregate locally instead of requesting Binance history
Example fix
# before
bar_type = BarType.from_str('BTCUSDT-PERP.BINANCE-1-MINUTE-MID-EXTERNAL')
# after
bar_type = BarType.from_str('BTCUSDT-PERP.BINANCE-1-MINUTE-LAST-EXTERNAL') Defensive patterns
Strategy: validation
Validate before calling
from nautilus_trader.model.enums import PriceType
def is_requestable_binance_bar(bar_type) -> bool:
return bar_type.spec.price_type == PriceType.LAST
if not is_requestable_binance_bar(request_bar_type):
raise ValueError(f'{request_bar_type} is {request_bar_type.spec.price_type}; Binance kline history is LAST only') Type guard
def is_last_price_bar(bar_type) -> bool:
return bar_type.spec.price_type == PriceType.LAST Try / catch
try:
actor.request_bars(bar_type, start=start_ts, end=end_ts)
except Exception as e:
if 'require LAST price type' in str(e):
raise ValueError('Request the -LAST- bar type for Binance history; build quote-price bars locally from book data') from e
raise Prevention
- Standardise Binance bar configs on LAST price; MID/BID/ASK klines are unavailable from the exchange
- Validate price type together with aggregation source before any history request
When it happens
Trigger: `request_bars` with a BarType such as `BTCUSDT-PERP.BINANCE-1-MINUTE-MID-EXTERNAL`, `-BID-EXTERNAL`, or `-ASK-EXTERNAL`. (Price type is checked after aggregation source, so an INTERNAL MID bar fails with the aggregation error first.)
Common situations: Strategies standardised on MID bars across venues; generic backfill code requesting whatever bar types a config lists; assuming quote-price klines exist on Binance.
Related errors
- historical BinanceBar requests require LAST price type
- historical BinanceBar requests require EXTERNAL aggregation
- historical BinanceBar requests require time aggregation
- Binance historical bars require EXTERNAL aggregation
- historical open interest request requires `period` metadata
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/fc745726de4dd2c4.
Report an issue: GitHub.