nautechsystems/nautilus_trader · error

Derive only supports hour intervals 1, 4, 8

Error message

Derive only supports hour intervals 1, 4, 8

What it means

Validation branch in bar_spec_to_derive_period rejecting HOUR steps other than 1, 4, or 8: Derive candle periods are fixed seconds values (3600/14400/28800) and other hourly steps have no Derive equivalent.

Source

Thrown at crates/adapters/derive/src/websocket/parse.rs:664

/// # Errors
///
/// Returns an error if the aggregation or step has no Derive equivalent.
pub fn bar_spec_to_derive_period(aggregation: BarAggregation, step: u64) -> anyhow::Result<u32> {
    match aggregation {
        BarAggregation::Minute => match step {
            1 => Ok(60),
            5 => Ok(300),
            15 => Ok(900),
            30 => Ok(1800),
            _ => anyhow::bail!(
                "Derive only supports minute intervals 1, 5, 15, 30 (use HOUR for >= 60)"
            ),
        },
        BarAggregation::Hour => match step {
            1 => Ok(3600),
            4 => Ok(14400),
            8 => Ok(28800),
            _ => anyhow::bail!("Derive only supports hour intervals 1, 4, 8"),
        },
        BarAggregation::Day => {
            if step != 1 {
                anyhow::bail!("Derive only supports 1 DAY interval bars");
            }
            Ok(86400)
        }
        BarAggregation::Week => {
            if step != 1 {
                anyhow::bail!("Derive only supports 1 WEEK interval bars");
            }
            Ok(604800)
        }
        _ => anyhow::bail!("Derive does not support {aggregation:?} bars"),
    }
}

fn timestamp_seconds_to_nanos(value: u64, field: &str) -> anyhow::Result<UnixNanos> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use hour steps 1, 4, or 8 only
  2. For 24-hour bars, use BarAggregation::Day with step 1
  3. For other multiples, aggregate from a supported base interval in the strategy
  4. Update the BarType specification in the bar request/subscription

Example fix

// before
BarAggregation::Hour, step: 12
// after
BarAggregation::Hour, step: 8 // or Day/1 for 24h
Defensive patterns

Strategy: validation

Validate before calling

fn hour_step_ok(step: u64) -> bool { matches!(step, 1 | 4 | 8) }
assert!(hour_step_ok(bar_spec.step), "Hour bars must be 1, 4, or 8");

Try / catch

match bar_spec_to_derive_period(&BarAggregation::Hour, step) {
    Ok(p) => subscribe(p),
    Err(e) if e.to_string().contains("hour intervals") => {
        // fall back to nearest supported step
        subscribe(bar_spec_to_derive_period(&BarAggregation::Hour, nearest_supported(step))?)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Requesting bars with BarAggregation::Hour and a step not in {1,4,8} (e.g. 2, 6, 12, 24), via request_bars or bar config.

Common situations: Requesting 12-hour or 24-hour bars (24h should be Day step 1); configs ported from venues supporting arbitrary hour intervals.

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/90404652c65198e3. Report an issue: GitHub.