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

  1. Use an EXTERNAL aggregation source bar type: 'BTC-USD.COINBASE-1-MINUTE-EXTERNAL'
  2. In Python, create the bar type with BarType.from_str(...-EXTERNAL) or aggregation_source=AggregationSource.EXTERNAL
  3. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/c757b15f07d49d58. Report an issue: GitHub.