nautechsystems/nautilus_trader · error · anyhow::Error

Binance Futures does not support second-level kline…

Error message

Binance Futures does not support second-level kline intervals

What it means

Binance Futures kline streams do not support second-level intervals; the smallest supported kline interval is one minute. The handler converts the bar spec to a BinanceKlineInterval and rejects Second1 before building the kline_ stream name.

Solutions

  1. Use a 1-minute or larger interval for external Binance Futures bars
  2. Request second bars with AggregationSource::Internal so the node aggregates from trade ticks instead of using Binance klines
  3. Change the bar aggregation spec in the strategy config to MINUTE or higher

Example fix

// before
BarType::from_spec(BarSpecification::new(1, BarAggregation::Second, PriceType::Last))
// after
BarType::from_spec(BarSpecification::new(1, BarAggregation::Minute, PriceType::Last))
Defensive patterns

Strategy: validation

Validate before calling

fn supports_futures_interval(spec: &BarSpecification) -> bool {
    !(spec.aggregation == BarAggregation::Second)
}

Type guard

fn is_external_minute_plus(bar_type: &BarType) -> bool {
    bar_type.aggregation_source() == AggregationSource::External
        && !matches!(bar_type.spec().aggregation, BarAggregation::Second)
}

Try / catch

match client.subscribe_bars(cmd) {
    Err(e) if e.to_string().contains("second-level kline") => {
        log::warn!("falling back to internal aggregation for {}", cmd.bar_type);
        subscribe_internally_aggregated(cmd.bar_type)?;
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling SubscribeBars with a bar_type whose spec aggregates on 1-second intervals (e.g. 1-SECOND-LAST) on the Binance Futures data client.

Common situations: High-frequency bar configs copied from venues that support sub-minute bars; generic bar-subscription loops that pass through any bar spec unchanged; users assuming Binance spot (which may differ) behavior applies to futures.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/4190b194d7d3c3a1. Report an issue: GitHub.

Appendix: source

Thrown at crates/adapters/binance/src/futures/data.rs:2079

        // Binance Futures uses aggTrade for aggregate trades
        let stream = format!("{}@aggTrade", format_binance_stream_symbol(&instrument_id));

        self.spawn_ws(
            async move {
                ws.subscribe(vec![stream])
                    .await
                    .context("trades subscription")
            },
            "trade subscription",
        );
        Ok(())
    }

    fn subscribe_bars(&mut self, cmd: SubscribeBars) -> anyhow::Result<()> {
        let bar_type = cmd.bar_type;
        let ws = self.ws_client.clone();
        let interval = bar_spec_to_binance_interval(bar_type.spec())?;
        anyhow::ensure!(
            interval != crate::common::enums::BinanceKlineInterval::Second1,
            "Binance Futures does not support second-level kline intervals"
        );

        let stream = format!(
            "{}@kline_{}",
            format_binance_stream_symbol(&bar_type.instrument_id()),
            interval.as_str()
        );

        self.spawn_ws(
            async move {
                ws.subscribe(vec![stream])
                    .await
                    .context("bars subscription")
            },
            "bar subscription",
        );

View on GitHub (pinned to 18893faf8b)