nautechsystems/nautilus_trader · error

Binance Futures does not support second-level kline interval

Error message

Binance Futures does not support second-level kline intervals

What it means

Thrown inside request_binance_bars when the BarAggregation is Second. Binance's futures kline endpoint has no sub-minute interval (its smallest interval is 1m), so any second-level bar request cannot be mapped to a venue interval string and the match arm bails immediately with this fixed message.

Source

Thrown at crates/adapters/binance/src/futures/http/client.rs:2984

    /// Returns an error if the bar type is not supported, instrument is not cached,
    /// or the request fails.
    pub async fn request_binance_bars(
        &self,
        bar_type: BarType,
        start: Option<Timestamp>,
        end: Option<Timestamp>,
        limit: Option<u32>,
    ) -> anyhow::Result<Vec<BinanceBar>> {
        anyhow::ensure!(
            bar_type.aggregation_source() == AggregationSource::External,
            "Only EXTERNAL aggregation is supported"
        );

        let spec = bar_type.spec();
        let step = spec.step.get();
        let interval = match spec.aggregation {
            BarAggregation::Second => {
                anyhow::bail!("Binance Futures does not support second-level kline intervals")
            }
            BarAggregation::Minute => format!("{step}m"),
            BarAggregation::Hour => format!("{step}h"),
            BarAggregation::Day => format!("{step}d"),
            BarAggregation::Week => format!("{step}w"),
            BarAggregation::Month => format!("{step}M"),
            a => anyhow::bail!("Binance Futures does not support {a:?} aggregation"),
        };

        let instrument_id = bar_type.instrument_id();
        let (symbol, price_precision, size_precision) =
            self.cached_precisions_by_id(instrument_id)?;

        let params = BinanceKlinesParams {
            symbol,
            interval,
            start_time: start.map(|dt| dt.as_millisecond()),
            end_time: end.map(|dt| dt.as_millisecond()),

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Use Minute (or coarser) aggregation for venue kline requests
  2. For second bars, fetch 1-minute klines or aggTrades and aggregate down locally
  3. Filter second-level bar types out of batch historical loaders with a skip-and-log instead of failing the whole run

Example fix

// before
let bar_type: BarType = "BTCUSDT.BINANCE_PERP-1-SECOND-LAST-EXTERNAL".parse()?;
let bars = client.request_binance_bars(bar_type, start, end, None).await?;

// after
let bar_type: BarType = "BTCUSDT.BINANCE_PERP-1-MINUTE-LAST-EXTERNAL".parse()?;
let bars = client.request_binance_bars(bar_type, start, end, None).await?;
Defensive patterns

Strategy: type-guard

Validate before calling

use nautilus_model::data::bar::BarAggregation;
if bar_type.spec().aggregation == BarAggregation::Second {
    log::warn!("second bars unsupported on futures; skipping {bar_type}");
}

Type guard

fn is_supported_kline_aggregation(bar_type: &BarType) -> bool {
    !matches!(
        bar_type.spec().aggregation,
        BarAggregation::Second | BarAggregation::Tick | BarAggregation::Volume | BarAggregation::Value
    )
}

Try / catch

Filter second-level bar types out of batch loaders before calling; on error for a single request, skip and continue the batch.

Prevention

When it happens

Trigger: Passing a BarType like 'BTCUSDT.BINANCE_PERP-1-SECOND-LAST-EXTERNAL' to request_binance_bars; generic multi-timeframe loaders that enumerate 1s/5s/15s bars and forward them all to the venue; porting strategies from venues that do support second klines (e.g. some spot APIs or other exchanges).

Common situations: Sub-minute strategies (market making, latency-sensitive signals) requesting venue history; the aggregation step mapping second bars to the interval formatter; users assuming spot and futures kline granularity are identical.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/38d81b9ac30465e7. Report an issue: GitHub.