nautechsystems/nautilus_trader · error
Lighter candles only support EXTERNAL aggregation
Error message
Lighter candles only support EXTERNAL aggregation
What it means
Converting a Nautilus `BarType` into a `LighterCandleResolution` requires the bar's aggregation source to be `AggregationSource::External`, because Lighter provides candles directly and the adapter does not aggregate bars internally. `TryFrom<&BarType>` fails with this error for any internally-aggregated bar type.
Source
Thrown at crates/adapters/lighter/src/common/enums.rs:250
Self::OneWeek => (1, BarAggregation::Week),
};
BarSpecification::new(step, aggregation, PriceType::Last)
}
/// Returns `true` when this resolution is offered on the candle WebSocket stream.
///
/// `1w` is REST-only; the streaming channel only carries `1m`..=`1d`.
#[must_use]
pub const fn is_ws_streamable(self) -> bool {
!matches!(self, Self::OneWeek)
}
}
impl TryFrom<&BarType> for LighterCandleResolution {
type Error = anyhow::Error;
fn try_from(value: &BarType) -> Result<Self, Self::Error> {
anyhow::ensure!(
value.aggregation_source() == AggregationSource::External,
"Lighter candles only support EXTERNAL aggregation",
);
let spec = value.spec();
anyhow::ensure!(
spec.price_type == PriceType::Last,
"Lighter candles only support LAST price type",
);
let step = spec.step.get();
match spec.aggregation {
BarAggregation::Minute => match step {
1 => Ok(Self::OneMinute),
5 => Ok(Self::FiveMinute),
15 => Ok(Self::FifteenMinute),
30 => Ok(Self::ThirtyMinute),
_ => anyhow::bail!("unsupported Lighter candle minute step: {step}"),View on GitHub (pinned to 18893faf8b)
Solutions
- Create the BarType with `AggregationSource::External` (e.g. `BarType::new(instrument_id, BarAggregation::Minute, PriceType::Last, AggregationSource::External)`).
- Update any bar spec strings in config from `...-INTERNAL` to `...-EXTERNAL`.
- If internal aggregation is required, aggregate locally from Lighter trades/ticks instead of using Lighter candles.
Example fix
// before
let bar_type = BarType::from("BTCUSDT-PERP.LIGHTER-1-MINUTE-LAST-INTERNAL");
// after
let bar_type = BarType::from("BTCUSDT-PERP.LIGHTER-1-MINUTE-LAST-EXTERNAL"); Defensive patterns
Strategy: validation
Validate before calling
if bar_type.aggregation_source() != AggregationSource::External {
panic!("Lighter candles require EXTERNAL aggregation");
} Type guard
fn is_external_bar(bar: &BarType) -> bool {
bar.aggregation_source() == AggregationSource::External
} Try / catch
let resolution = LighterCandleResolution::try_from(&bar_type)
.map_err(|e| { eprintln!("bad bar type {bar_type}: {e:#}"); e })?; Prevention
- Always declare Lighter bar types with -EXTERNAL aggregation.
- Validate bar spec strings in config at startup.
- Never copy INTERNAL bar specs from other venues.
When it happens
Trigger: Requesting Lighter candle data with a BarType whose spec uses `AggregationSource::Internal` (e.g. bars aggregated by the Nautilus data engine from ticks).
Common situations: Subscribing to bars with the default internal aggregation instead of declaring EXTERNAL bars; copying BarType strings like `BTCUSDT-PERP.LIGHTER-*MINUTE-INTERNAL` from a config that targeted a different venue.
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/245c627b9b9f67ce.
Report an issue: GitHub.