nautechsystems/nautilus_trader · error

Unsupported hour step: {step}

Error message

Unsupported hour step: {step}

What it means

Validation branch in bar_type_to_granularity rejecting HOUR steps other than 1/2/6/24-equivalents supported by Coinbase: the requested hourly step has no matching Coinbase granularity, so the bar type cannot be requested.

Source

Thrown at crates/adapters/coinbase/src/common/parse.rs:144

        bar_type.aggregation_source() == AggregationSource::External,
        "Only EXTERNAL aggregation is supported"
    );

    let step = spec.step.get();

    match spec.aggregation {
        BarAggregation::Minute => match step {
            1 => Ok(CoinbaseGranularity::OneMinute),
            5 => Ok(CoinbaseGranularity::FiveMinute),
            15 => Ok(CoinbaseGranularity::FifteenMinute),
            30 => Ok(CoinbaseGranularity::ThirtyMinute),
            _ => anyhow::bail!("Unsupported minute step: {step}"),
        },
        BarAggregation::Hour => match step {
            1 => Ok(CoinbaseGranularity::OneHour),
            2 => Ok(CoinbaseGranularity::TwoHour),
            6 => Ok(CoinbaseGranularity::SixHour),
            _ => anyhow::bail!("Unsupported hour step: {step}"),
        },
        BarAggregation::Day => match step {
            1 => Ok(CoinbaseGranularity::OneDay),
            _ => anyhow::bail!("Unsupported day step: {step}"),
        },
        other => anyhow::bail!("Unsupported aggregation: {other}"),
    }
}

#[cfg(test)]
mod tests {
    use rstest::rstest;

    use super::*;

    #[rstest]
    #[case(
        "BTC-USD.COINBASE-1-MINUTE-LAST-EXTERNAL",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Switch the BarType to a supported hour step: 1, 2, or 6 hours.
  2. Build larger windows locally by aggregating 1-hour bars.
  3. Source those bars from an adapter whose exchange supports the desired hour step.

Example fix

// before
"ETH-USD.COINBASE-4-HOUR.INTERNAL"
// after
"ETH-USD.COINBASE-6-HOUR.INTERNAL"
Defensive patterns

Strategy: validation

Validate before calling

const COINBASE_HOUR_STEPS: [u64; 3] = [1, 2, 6];
assert!(COINBASE_HOUR_STEPS.contains(&bar_type.spec().step.get()),
    "Coinbase supports hour steps: 1, 2, 6");

Try / catch

match bar_type_to_granularity(&bar_type) {
    Ok(g) => request_candles(g),
    Err(e) if e.to_string().contains("Unsupported hour step") => {
        request_candles(CoinbaseGranularity::OneHour); // aggregate locally
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Requesting bars (via `request_bars`) with a `BarType` like `...-4-HOUR` or `...-12-HOUR`; Coinbase simply does not offer those granularities.

Common situations: Config reuse from exchanges with richer hour granularity sets (e.g. Binance supports 4h/8h/12h); copy-pasted bar specifications across adapters.

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/27b6ddebf084c14f. Report an issue: GitHub.