nautechsystems/nautilus_trader · error

Unsupported month interval: {step}M

Error message

Unsupported month interval: {step}M

What it means

Thrown by bar_spec_to_binance_interval when converting a Nautilus BarSpecification to a Binance kline interval. Binance's kline API only offers a fixed set of intervals per time unit, and for months only 1M exists, so any month step other than 1 has no server-side equivalent. The adapter refuses the mapping instead of silently returning wrong-sized bars.

Source

Thrown at crates/adapters/binance/src/common/parse.rs:1467

            2 => BinanceKlineInterval::Hour2,
            4 => BinanceKlineInterval::Hour4,
            6 => BinanceKlineInterval::Hour6,
            8 => BinanceKlineInterval::Hour8,
            12 => BinanceKlineInterval::Hour12,
            _ => anyhow::bail!("Unsupported hour interval: {step}h"),
        },
        BarAggregation::Day => match step {
            1 => BinanceKlineInterval::Day1,
            3 => BinanceKlineInterval::Day3,
            _ => anyhow::bail!("Unsupported day interval: {step}d"),
        },
        BarAggregation::Week => match step {
            1 => BinanceKlineInterval::Week1,
            _ => anyhow::bail!("Unsupported week interval: {step}w"),
        },
        BarAggregation::Month => match step {
            1 => BinanceKlineInterval::Month1,
            _ => anyhow::bail!("Unsupported month interval: {step}M"),
        },
        agg => anyhow::bail!("Unsupported bar aggregation for Binance: {agg:?}"),
    };

    Ok(interval)
}

pub(crate) fn quote_to_l1_deltas(quote: QuoteTick, sequence: u64) -> OrderBookDeltas {
    let bid_action = if quote.bid_size.is_zero() {
        BookAction::Delete
    } else {
        BookAction::Update
    };
    let ask_action = if quote.ask_size.is_zero() {
        BookAction::Delete
    } else {
        BookAction::Update
    };

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Change the BarType to the supported 1-month step: 'BTCUSDT.BINANCE-1-MONTH-LAST-INTERNAL'.
  2. If you need 3M/6M bars, subscribe to or request 1-MONTH bars and aggregate them in your strategy (or via the data catalog) instead of asking the exchange.
  3. Check the interval table in bar_spec_to_binance_interval (parse.rs) for all supported steps: 1s; 1/3/5/15/30m; 1/2/4/6/8/12h; 1/3d; 1w; 1M.

Example fix

# before
bar_type = BarType.from_str('BTCUSDT.BINANCE-3-MONTH-LAST-INTERNAL')
client.subscribe_bars(BarSubscription(bar_type))

# after
bar_type = BarType.from_str('BTCUSDT.BINANCE-1-MONTH-LAST-INTERNAL')
client.subscribe_bars(BarSubscription(bar_type))
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED_STEPS = {
    'SECOND': {1}, 'MINUTE': {1, 3, 5, 15, 30}, 'HOUR': {1, 2, 4, 6, 8, 12},
    'DAY': {1, 3}, 'WEEK': {1}, 'MONTH': {1},
}

def binance_bar_spec_supported(bar_spec) -> bool:
    agg = bar_spec.aggregation_string  # e.g. 'MINUTE'
    step = int(bar_spec.step)
    return step in SUPPORTED_STEPS.get(agg, set())

Type guard

def is_supported_binance_interval(bar_type) -> bool:
    spec = bar_type.spec
    return spec.aggregation_string in (
        'SECOND', 'MINUTE', 'HOUR', 'DAY', 'WEEK', 'MONTH'
    ) and binance_bar_spec_supported(spec)

Prevention

When it happens

Trigger: Subscribing to bars or requesting historical bars with a BarType whose aggregation is MONTH and step != 1, e.g. 'BTCUSDT.BINANCE-3-MONTH-LAST-INTERNAL' passed to subscribe_bars / request_bars, or used in a BacktestEngine catalog request routed through the Binance data client.

Common situations: Porting a strategy from another platform (TradingView '3M' charts, MT5 MN3) that supports multi-month bars; building BarType programmatically from a config file where the step multiplier is user-controlled; assuming Binance supports every composite interval because 1m/5m/1h composites work.

Related errors


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