nautechsystems/nautilus_trader · error · anyhow::Error
Only EXTERNAL aggregation is supported
Error message
Only EXTERNAL aggregation is supported
What it means
Hyperliquid bars must be requested with EXTERNAL aggregation source: the adapter fetches pre-aggregated candles from the exchange HTTP API rather than aggregating ticks internally. bar_type_to_interval throws this error when a bar type with any other aggregation source (e.g. INTERNAL) is passed to request_bars, subscribe_bars, or unsubscribe_bars.
Source
Thrown at crates/adapters/hyperliquid/src/common/parse.rs:441
}
} else {
// No market price available, default to SL for safety
HyperliquidExchangeTpSl::Sl
}
}
}
}
/// Converts a Nautilus `BarType` to a Hyperliquid bar interval.
///
/// # Errors
///
/// Returns an error if the bar type uses an unsupported aggregation or step value.
pub fn bar_type_to_interval(bar_type: &BarType) -> anyhow::Result<HyperliquidBarInterval> {
let spec = bar_type.spec();
let step = spec.step.get();
anyhow::ensure!(
bar_type.aggregation_source() == AggregationSource::External,
"Only EXTERNAL aggregation is supported"
);
let interval = match spec.aggregation {
BarAggregation::Minute => match step {
1 => OneMinute,
3 => ThreeMinutes,
5 => FiveMinutes,
15 => FifteenMinutes,
30 => ThirtyMinutes,
_ => anyhow::bail!("Unsupported minute step: {step}"),
},
BarAggregation::Hour => match step {
1 => OneHour,
2 => TwoHours,
4 => FourHours,
8 => EightHours,View on GitHub (pinned to 18893faf8b)
Solutions
- Construct the BarType with AggregationSource::External (e.g. use 'BTC-PERP.HYPERLIQUID-1-MINUTE.EXTERNAL' style bar type strings)
- Set the strategy/config to use external aggregation for Hyperliquid data subscriptions
- If internal aggregation is required, use an aggregating data engine/adapter that supports it instead of the Hyperliquid adapter directly
- Validate bar types at startup against bar_type.aggregation_source() before subscribing
Example fix
// before let bar_type = BarType::new(instrument_id, BarAggregation::Minute, 1, AggregationSource::Internal); // after let bar_type = BarType::new(instrument_id, BarAggregation::Minute, 1, AggregationSource::External);
Defensive patterns
Strategy: validation
Validate before calling
if bar_type.aggregation_source() != AggregationSource::External {
return Err(anyhow!("Hyperliquid requires EXTERNAL aggregation, got {:?}", bar_type.aggregation_source()));
}
client.request_bars(bar_type)?; Type guard
fn is_external_bar_type(bt: &BarType) -> bool {
bt.aggregation_source() == AggregationSource::External
} Try / catch
match bar_type_to_interval(&bar_type) {
Err(e) if e.to_string().contains("Only EXTERNAL aggregation") => {
eprintln!("Rebuild bar_type with AggregationSource::External");
}
Err(e) => return Err(e),
Ok(interval) => subscribe(interval),
} Prevention
- Always specify .EXTERNAL in Hyperliquid bar type strings
- Validate bar type aggregation source at strategy startup
- Use an internal-aggregation-capable engine if INTERNAL bars are required
When it happens
Trigger: Calling request_bars/subscribe_bars with a BarType whose aggregation_source is not AggregationSource::External — e.g. a bar type built with INTERNAL aggregation or with the wrong aggregation source specifier in the bar type string.
Common situations: Configuring strategy subscriptions with INTERNAL bar aggregation while using the Hyperliquid data client; copying bar-type strings from adapters that support internal aggregation; defaulting bar aggregation source in config without specifying External.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Invalid Hyperliquid bar interval: {s}
- Unsupported minute step: {step}
- Unsupported hour step: {step}
- Unsupported day step: {step}
- Hyperliquid does not support {a:?} aggregation
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a0057512a913c4d5.
Report an issue: GitHub.