nautechsystems/nautilus_trader · error
Only EXTERNAL aggregation is supported
Error message
Only EXTERNAL aggregation is supported
What it means
Coinbase bar requests must use bars aggregated externally (by the exchange), not internally by Nautilus. bar_type_to_granularity checks the bar type's aggregation source and raises this error for INTERNAL aggregation.
Source
Thrown at crates/adapters/coinbase/src/common/parse.rs:125
/// # Errors
///
/// Returns an error when the nanosecond value is outside the Jiff timestamp range.
pub fn format_rfc3339_from_nanos(ts: UnixNanos) -> anyhow::Result<String> {
Ok(ts
.to_datetime_utc()
.display_with_offset(Offset::UTC)
.to_string())
}
/// Converts a Nautilus [`BarType`] to a [`CoinbaseGranularity`].
///
/// # Errors
///
/// Returns an error if the bar type uses an unsupported aggregation or step value.
pub fn bar_type_to_granularity(bar_type: &BarType) -> anyhow::Result<CoinbaseGranularity> {
let spec = bar_type.spec();
anyhow::ensure!(
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),View on GitHub (pinned to 18893faf8b)
Solutions
- Use an EXTERNAL aggregation source bar type: 'BTC-USD.COINBASE-1-MINUTE-EXTERNAL'
- In Python, create the bar type with BarType.from_str(...-EXTERNAL) or aggregation_source=AggregationSource.EXTERNAL
- Aggregate internally yourself if you must use INTERNAL bars instead of requesting from Coinbase
Example fix
# before
bar_type = BarType.from_str("BTC-USD.COINBASE-1-MINUTE-INTERNAL")
client.request_bars(bar_type)
# after
bar_type = BarType.from_str("BTC-USD.COINBASE-1-MINUTE-EXTERNAL")
client.request_bars(bar_type) Defensive patterns
Strategy: validation
Validate before calling
if bar_type.aggregation_source != AggregationSource.EXTERNAL:
bar_type = BarType.from_str(str(bar_type).replace('-INTERNAL', '-EXTERNAL')) Try / catch
try:
client.request_bars(bar_type)
except ValueError as e:
if 'Only EXTERNAL aggregation' in str(e):
client.request_bars(to_external(bar_type)) Prevention
- Always build venue-fetchable bar types with -EXTERNAL
- Keep a helper that converts internal bar types to external before historical requests
- Document that Coinbase history endpoints only serve exchange-aggregated bars
When it happens
Trigger: Calling request_bars (or anything using bar_type_to_granularity) with a BarType whose aggregation_source is AggregationSource::Internal, e.g. BarType.from_str("BTC-USD.COINBASE-1-MINUTE-INTERNAL").
Common situations: Constructing bar types with the default/internal aggregation source and then trying to fetch historical bars from Coinbase; copying bar type strings between venues without flipping the source.
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
- Derive only supports minute intervals 1, 5, 15, 30 (use HOUR
- Derive only supports hour intervals 1, 4, 8
- Derive only supports 1 DAY interval bars
- Invalid step in bar_type.spec.step: {step} for aggregation={
- Invalid step in bar_type.spec.step: {step} for aggregation={
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c757b15f07d49d58.
Report an issue: GitHub.