nautechsystems/nautilus_trader · error

Invalid step in bar_type.spec.step: {step} for aggregation={

Error message

Invalid step in bar_type.spec.step: {step} for aggregation={aggregation}. {reason}

What it means

invalid_interval_step builds the canonical error for a bar specification step that cannot be used in time arithmetic: it may overflow i64 when converted, overflow when scaled by a multiplier or into days, or fail SignedDuration conversion. The original reason (e.g. 'step overflows i64 days') is embedded in the message. It guards the time-based bar aggregation machinery against unusable interval configurations.

Source

Thrown at crates/model/src/data/bar.rs:406

        .map_err(|_| invalid_interval_step(step, aggregation, "interval overflows nanoseconds"))?;

    Ok(duration)
}

fn try_scaled_days(
    step: usize,
    aggregation: BarAggregation,
    step_i64: i64,
    multiplier: i64,
) -> anyhow::Result<SignedDuration> {
    let days = step_i64
        .checked_mul(multiplier)
        .ok_or_else(|| invalid_interval_step(step, aggregation, "step overflows i64 days"))?;
    try_duration_days(days).map_err(|e| invalid_interval_step(step, aggregation, &e.to_string()))
}

fn invalid_interval_step(step: usize, aggregation: BarAggregation, reason: &str) -> anyhow::Error {
    anyhow::anyhow!(
        "Invalid step in bar_type.spec.step: {step} for aggregation={aggregation}. {reason}"
    )
}

/// Converts a bar specification step to `i64` for time arithmetic.
///
/// # Panics
///
/// Panics if `step` exceeds the `i64` range.
fn step_to_i64(step: NonZeroUsize) -> i64 {
    i64::try_from(step.get()).expect("`step` exceeds i64 range")
}

/// Represents a bar aggregation specification including a step, aggregation
/// method/rule and price type.
#[repr(C)]
#[derive(
    Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Serialize, Deserialize, Builder,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Validate bar_type.spec.step is a small positive integer before building the aggregation
  2. Bound step × multiplier against i64 limits in your configuration layer
  3. Handle the returned anyhow::Error and reject the invalid BarType instead of unwrapping

Example fix

// before
let interval = try_time_interval(step, aggregation).unwrap();
// after
let interval = try_time_interval(step, aggregation)
    .map_err(|e| anyhow::anyhow!("bad bar interval: {e}"))?;
Defensive patterns

Strategy: validation

Validate before calling

fn step_is_valid(step: usize) -> bool {
    step > 0 && step <= i64::MAX as usize / 24 / 86_400_000_000 // safely convertible
}

Try / catch

let interval = try_time_interval(step, aggregation)
    .map_err(|e| anyhow::anyhow!("invalid bar interval: {e}"))?;

Prevention

When it happens

Trigger: Constructing bar aggregation intervals (try_time_interval, try_scaled_days) where step exceeds i64, step×multiplier overflows i64 days, or the resulting day count fails try_duration_days — e.g. BarType/BarAggregation specs built from unvalidated user input.

Common situations: User/config-provided bar intervals that are zero-negative or astronomically large; programmatic BarType construction with unchecked step values; Python-side integration passing oversized ints into spec.step.

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