nautechsystems/nautilus_trader · error
Cannot subscribe for synthetic instrument `InstrumentClose`
Error message
Cannot subscribe for synthetic instrument `InstrumentClose` data
What it means
InstrumentClose data comes from venues at session close and cannot be produced for locally generated synthetic instruments. The engine rejects SubscribeCommand::InstrumentClose for any synthetic instrument ID with this error.
Source
Thrown at crates/data/src/engine/mod.rs:1102
}
SubscribeCommand::Quotes(cmd)
if self.is_spread_quote_command(cmd.instrument_id, cmd.params.as_ref()) =>
{
self.subscribe_spread_quotes(cmd);
return Ok(());
}
SubscribeCommand::Trades(cmd) if cmd.instrument_id.is_synthetic() => {
self.subscribe_synthetic_trades(cmd.instrument_id);
return Ok(());
}
SubscribeCommand::Instrument(cmd) if cmd.instrument_id.is_synthetic() => {
anyhow::bail!("Cannot subscribe for synthetic instrument `Instrument` data");
}
SubscribeCommand::InstrumentStatus(cmd) if cmd.instrument_id.is_synthetic() => {
anyhow::bail!("Cannot subscribe for synthetic instrument `InstrumentStatus` data");
}
SubscribeCommand::InstrumentClose(cmd) if cmd.instrument_id.is_synthetic() => {
anyhow::bail!("Cannot subscribe for synthetic instrument `InstrumentClose` data");
}
SubscribeCommand::OptionGreeks(cmd) if cmd.instrument_id.is_synthetic() => {
anyhow::bail!("Cannot subscribe for synthetic instrument `OptionGreeks` data");
}
_ => {} // Do nothing else
}
let retained = cmd.clone();
// Book ownership, including failed acquisitions, is already counted by the engine
let retain_on_failure = !matches!(
&cmd,
SubscribeCommand::BookDeltas(_) | SubscribeCommand::BookDepth10(_)
);
#[cfg(feature = "streaming")]
let cmd = self.subscribe_command_with_prefilled_start_ns(cmd)?;
View on GitHub (pinned to 18893faf8b)
Solutions
- Skip synthetic instrument IDs when subscribing to InstrumentClose data.
- Use the supported synthetic streams (e.g. Trades) for synthetic instruments.
- Restrict InstrumentClose subscriptions to real venue-listed instruments.
Example fix
// before
subscribe_all(engine, synthetic_id); // includes InstrumentClose
// after
if !synthetic_id.is_synthetic() {
subscribe_all(engine, synthetic_id);
} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust
fn can_subscribe_instrument_close(id: InstrumentId) -> bool { !id.is_synthetic() } Type guard
// Rust
fn is_venue_instrument(id: &InstrumentId) -> bool {
!id.is_synthetic()
} Try / catch
// Rust
match engine.subscribe_instrument_close(id) {
Err(e) if e.to_string().contains("synthetic instrument `InstrumentClose`") => Ok(()),
r => r,
} Prevention
- Skip InstrumentClose subscriptions for synthetic IDs in bulk-subscribe helpers.
- Document which data types are real-venue-only and enforce it centrally.
- Prefer explicit per-type subscription lists over 'subscribe to everything' helpers.
When it happens
Trigger: Subscribing to InstrumentClose with an InstrumentId where is_synthetic() is true, typically via a loop subscribing to every data type for every instrument.
Common situations: Wide-net subscription utilities that cover all data types; porting real-market subscription configs to synthetic instrument strategies.
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 `OptionGreeks` dat
- Cannot unsubscribe from synthetic instrument `Instrument` da
- Cannot unsubscribe from synthetic instrument `InstrumentStat
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/20e7579e20f536f3.
Report an issue: GitHub.