nautechsystems/nautilus_trader · error
Cannot subscribe for externally aggregated synthetic instrum
Error message
Cannot subscribe for externally aggregated synthetic instrument bar data
What it means
NautilusTrader's DataEngine only supports synthetic instruments (instrument IDs like 'SYNTH.AAPL-...') when bars are aggregated internally by the engine's own bar aggregators. Subscribing to a synthetic bar type with AggregationSource::External would require the adapter/data source to feed pre-aggregated bars, which cannot exist for a synthetic instrument that no venue provides. The engine therefore rejects the subscription outright.
Source
Thrown at crates/data/src/engine/mod.rs:3243
"Calling client.execute_subscribe for BookDeltas: {}",
cmd.instrument_id
);
client.execute_subscribe(client_command);
} else {
log::error!(
"Cannot handle command: no client found for client_id={:?}, venue={:?}",
cmd.client_id,
cmd.venue,
);
}
}
fn subscribe_bars(&mut self, cmd: &SubscribeBars) -> anyhow::Result<()> {
match cmd.bar_type.aggregation_source() {
AggregationSource::Internal => self.start_bar_aggregation(cmd)?,
AggregationSource::External => {
if cmd.bar_type.instrument_id().is_synthetic() {
anyhow::bail!(
"Cannot subscribe for externally aggregated synthetic instrument bar data"
);
}
}
}
Ok(())
}
fn subscribe_synthetic_quotes(&mut self, instrument_id: InstrumentId) {
let synthetic = match self.cache.borrow().try_synthetic(&instrument_id).cloned() {
Ok(synthetic) => synthetic,
Err(e) => {
log::error!("Cannot subscribe to `QuoteTick` data for synthetic instrument: {e}");
return;
}
};
View on GitHub (pinned to 18893faf8b)
Solutions
- Remove the External aggregation source so the BarType uses internal aggregation (default); the engine will aggregate the synthetic bar itself via start_bar_aggregation.
- If external aggregation is truly needed, use a real (non-synthetic) instrument ID that the data client can provide bars for.
- Build the BarType explicitly with AggregationSource::Internal, e.g. BarType::new(instrument_id, spec, AggregationSource::Internal).
Example fix
// before let bar_type = BarType::new(synthetic_id, bar_spec, AggregationSource::External); strategy.subscribe_bars(bar_type)?; // after let bar_type = BarType::new(synthetic_id, bar_spec, AggregationSource::Internal); strategy.subscribe_bars(bar_type)?;
Defensive patterns
Strategy: validation
Validate before calling
if bar_type.instrument_id().is_synthetic() && bar_type.aggregation_source() == AggregationSource::External {
// rebuild with internal aggregation before subscribing
}
strategy.subscribe_bars(BarType::new(bar_type.instrument_id().clone(), bar_type.spec(), AggregationSource::Internal))?; Type guard
fn is_subscribable_synthetic_bar(bt: &BarType) -> bool {
!bt.instrument_id().is_synthetic() || bt.aggregation_source() == AggregationSource::Internal
} Try / catch
match strategy.subscribe_bars(bar_type) {
Err(e) if e.to_string().contains("externally aggregated synthetic") => {
strategy.subscribe_bars(BarType::new(bar_type.instrument_id().clone(), bar_type.spec(), AggregationSource::Internal))?;
}
r => r?,
} Prevention
- Default to internal aggregation when constructing BarTypes for synthetic instruments
- Never append the external aggregation suffix to synthetic instrument bar type strings
- Check is_synthetic() on the instrument id before choosing an aggregation source
When it happens
Trigger: Calling subscribe_bars (e.g. via strategy.subscribe_bars) with a BarType whose instrument_id is synthetic while the BarType's aggregation source is External — typically a BarType built with an explicit AggregationSource::External argument.
Common situations: Constructing BarType.from_str with an aggregation source suffix (e.g. ':external') on a synthetic instrument; copying a subscription snippet meant for real instruments and reusing it for synthetic ones; config files that set aggregation_source=external globally.
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
- Cannot subscribe for synthetic instrument `Instrument` data
- Cannot subscribe for synthetic instrument `InstrumentStatus`
- Cannot subscribe for synthetic instrument `InstrumentClose`
- Cannot subscribe for synthetic instrument `OptionGreeks` dat
- Cannot unsubscribe from synthetic instrument `Instrument` da
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b08f68ac60df063e.
Report an issue: GitHub.