nautechsystems/nautilus_trader · error
Timedelta not supported for aggregation type: {:?}
Error message
Timedelta not supported for aggregation type: {:?} What it means
`BarType::timedelta` (and its Python wrapper) returns the bar interval as a timedelta duration. Like `get_bar_interval`, it only supports the time-based aggregations; the `_ => panic!("Timedelta not supported for aggregation type: {:?}", self.aggregation)` arm fires for non-time aggregations such as Tick or Value. Called via `bar_close_from_open`, `py_timedelta`, and `py_get_interval_ns`.
Source
Thrown at crates/model/src/data/bar.rs:587
match self.aggregation {
BarAggregation::Millisecond => SignedDuration::from_millis(step),
BarAggregation::Second => SignedDuration::from_secs(step),
BarAggregation::Minute => SignedDuration::from_mins(step),
BarAggregation::Hour => SignedDuration::from_hours(step),
BarAggregation::Day => duration_days(step),
BarAggregation::Week => {
duration_days(step.checked_mul(7).expect("`step` overflows i64 days"))
}
BarAggregation::Month => {
// Proxy for comparing bar lengths
duration_days(step.checked_mul(30).expect("`step` overflows i64 days"))
}
BarAggregation::Year => {
// Proxy for comparing bar lengths
duration_days(step.checked_mul(365).expect("`step` overflows i64 days"))
}
_ => panic!(
"Timedelta not supported for aggregation type: {:?}",
self.aggregation
),
}
}
/// Return a value indicating whether the aggregation method is time-driven:
/// - [`BarAggregation::Millisecond`]
/// - [`BarAggregation::Second`]
/// - [`BarAggregation::Minute`]
/// - [`BarAggregation::Hour`]
/// - [`BarAggregation::Day`]
/// - [`BarAggregation::Week`]
/// - [`BarAggregation::Month`]
/// - [`BarAggregation::Year`]
#[must_use]
pub fn is_time_aggregated(&self) -> bool {
matches!(View on GitHub (pinned to 18893faf8b)
Solutions
- Check the aggregation is time based before calling `timedelta()`.
- Handle tick/value bar types separately (they close on events, not on a time interval).
- Fix the BarType aggregation in your config/spec so it matches the time-interval expectation.
Example fix
# before
interval = bar_type.timedelta() # panics for TICK bars
# after
from nautilus_trader.model.enums import BarAggregation
TIME_BASED = {BarAggregation.MILLISECOND, BarAggregation.SECOND, BarAggregation.MINUTE,
BarAggregation.HOUR, BarAggregation.DAY, BarAggregation.WEEK,
BarAggregation.MONTH, BarAggregation.YEAR}
if bar_type.spec().aggregation not in TIME_BASED:
raise ValueError(f"no timedelta for {bar_type.spec().aggregation}")
interval = bar_type.timedelta() Defensive patterns
Strategy: validation
Validate before calling
# Python
if bar_type.spec().aggregation in (BarAggregation.TICK, BarAggregation.VALUE):
raise ValueError("timedelta only defined for time-based bar aggregations")
interval = bar_type.timedelta() Type guard
def has_timedelta(bar_type) -> bool:
a = bar_type.spec().aggregation
from nautilus_trader.model.enums import BarAggregation
return a not in (BarAggregation.TICK, BarAggregation.VALUE) Prevention
- Check the aggregation enum before any timedelta/interval call
- Handle tick and value bars via event counts rather than durations
- Audit strategy configs for aggregations changed to TICK/VALUE after code was written
When it happens
Trigger: Calling `bar_type.timedelta()` (or `py_get_interval_ns` from Python) on a BarType whose aggregation is TICK or VALUE; computing bar close times generically over a list of bar types that includes tick/value bars.
Common situations: Python strategy code calling `.timedelta` on tick bars to compute close times; mixed bar-type dashboards; instrument configs where the aggregation was changed from SECOND to TICK but downstream code still asks for a timedelta.
Related errors
- Aggregation not time based
- Aggregation type {} not supported for time bars
- `handle_bar` is not implemented for `{}`
- {e}
- Binance Futures does not support {a:?} aggregation
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d92256c274416170.
Report an issue: GitHub.