nautechsystems/nautilus_trader · error

Unsupported bar step: {step} with aggregation {:?}

Error message

Unsupported bar step: {step} with aggregation {:?}

What it means

from_bar_spec covers only the specific (step, aggregation) pairs dYdX supports: 1/15/30 Minute, 1 Hour, 1 Day, 5 Minute, 15 Minute, 30 Minute, 4 Hour. Any other step value, regardless of aggregation, falls into the catch-all arm and bails with the step and aggregation in the message.

Source

Thrown at crates/adapters/dydx/src/common/enums.rs:687

impl DydxCandleResolution {
    /// Maps a Nautilus [`BarSpecification`] to a dYdX candle resolution.
    ///
    /// # Errors
    ///
    /// Returns an error if the step/aggregation combination is not supported.
    pub fn from_bar_spec(spec: &BarSpecification) -> anyhow::Result<Self> {
        match spec.step.get() {
            1 => match spec.aggregation {
                BarAggregation::Minute => Ok(Self::OneMinute),
                BarAggregation::Hour => Ok(Self::OneHour),
                BarAggregation::Day => Ok(Self::OneDay),
                _ => anyhow::bail!("Unsupported bar aggregation: {:?}", spec.aggregation),
            },
            5 if spec.aggregation == BarAggregation::Minute => Ok(Self::FiveMinutes),
            15 if spec.aggregation == BarAggregation::Minute => Ok(Self::FifteenMinutes),
            30 if spec.aggregation == BarAggregation::Minute => Ok(Self::ThirtyMinutes),
            4 if spec.aggregation == BarAggregation::Hour => Ok(Self::FourHours),
            step => anyhow::bail!(
                "Unsupported bar step: {step} with aggregation {:?}",
                spec.aggregation
            ),
        }
    }
}

/// dYdX network environment (mainnet vs testnet).
///
/// This selects the underlying Cosmos chain for transaction submission.
#[derive(
    Copy,
    Clone,
    Debug,
    Default,
    Display,
    PartialEq,
    Eq,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Snap the bar step to a supported dYdX interval: 1/5/15/30 Minute, 1/4 Hour, or 1 Day
  2. Download the nearest coarser supported interval and resample locally
  3. Verify the configured bar spec against dYdX's documented resolution list

Example fix

// before
let spec = BarSpecification::new(6.into(), BarAggregation::Hour, PriceType::Last);
// after
let spec = BarSpecification::new(4.into(), BarAggregation::Hour, PriceType::Last);
Defensive patterns

Strategy: validation

Validate before calling

fn is_dydx_bar_spec_supported(spec: &BarSpecification) -> bool {
    match spec.step.get() {
        1 => matches!(spec.aggregation, BarAggregation::Minute | BarAggregation::Hour | BarAggregation::Day),
        5 | 15 | 30 => spec.aggregation == BarAggregation::Minute,
        4 => spec.aggregation == BarAggregation::Hour,
        _ => false,
    }
}

Prevention

When it happens

Trigger: Requesting bars with a step that is not 1, 5, 15, or 30 for Minute, or not 1 or 4 for Hour — e.g. 2 Minute, 6 Hour, 7 Day bars against dYdX.

Common situations: Configuring arbitrary intervals like 2-hour or 3-minute candles that the exchange API does not offer; copying bar specs between adapters with different supported grids.

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/663493bfa0cfaeb5. Report an issue: GitHub.