nautechsystems/nautilus_trader · error
Cannot unsubscribe from synthetic instrument `Instrument` da
Error message
Cannot unsubscribe from synthetic instrument `Instrument` data
What it means
Unsubscribing from `Instrument` data is only valid for real instruments; for a synthetic instrument ID the engine never had a client subscription to remove, so UnsubscribeCommand::Instrument targeting a synthetic ID bails with this error. (Synthetic Trades unsubscribes are handled separately and succeed.)
Source
Thrown at crates/data/src/engine/mod.rs:1271
self.unsubscribe_option_chain(cmd);
return Ok(());
}
UnsubscribeCommand::Quotes(cmd) if cmd.instrument_id.is_synthetic() => {
self.unsubscribe_synthetic_quotes(cmd.instrument_id);
return Ok(());
}
UnsubscribeCommand::Quotes(cmd)
if self.is_spread_quote_command(cmd.instrument_id, cmd.params.as_ref()) =>
{
self.unsubscribe_spread_quotes(cmd);
return Ok(());
}
UnsubscribeCommand::Trades(cmd) if cmd.instrument_id.is_synthetic() => {
self.unsubscribe_synthetic_trades(cmd.instrument_id);
return Ok(());
}
UnsubscribeCommand::Instrument(cmd) if cmd.instrument_id.is_synthetic() => {
anyhow::bail!("Cannot unsubscribe from synthetic instrument `Instrument` data");
}
UnsubscribeCommand::InstrumentStatus(cmd) if cmd.instrument_id.is_synthetic() => {
anyhow::bail!(
"Cannot unsubscribe from synthetic instrument `InstrumentStatus` data"
);
}
UnsubscribeCommand::InstrumentClose(cmd) if cmd.instrument_id.is_synthetic() => {
anyhow::bail!(
"Cannot unsubscribe from synthetic instrument `InstrumentClose` data"
);
}
UnsubscribeCommand::OptionGreeks(cmd) if cmd.instrument_id.is_synthetic() => {
anyhow::bail!("Cannot unsubscribe from synthetic instrument `OptionGreeks` data");
}
_ => {}
}
if let Some(client) = self.get_command_client(cmd.client_id(), cmd.venue()) {View on GitHub (pinned to 18893faf8b)
Solutions
- Skip synthetic instrument IDs in Instrument unsubscribe calls (guard with is_synthetic()).
- Track which streams were actually subscribed and unsubscribe only those.
- For synthetic data, use the supported unsubscribe path (synthetic Trades) or simply drop the synthetic generator state.
Example fix
// before
engine.unsubscribe_instruments(synthetic_id)?;
// after
if !synthetic_id.is_synthetic() {
engine.unsubscribe_instruments(synthetic_id)?;
} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust
if !instrument_id.is_synthetic() {
engine.unsubscribe_instruments(instrument_id)?;
} Type guard
// Rust
fn needs_instrument_unsubscribe(id: &InstrumentId) -> bool {
!id.is_synthetic()
} Try / catch
// Rust
match engine.unsubscribe_instruments(id) {
Err(e) if e.to_string().contains("unsubscribe from synthetic instrument `Instrument`") => Ok(()),
r => r,
} Prevention
- Track actual subscriptions and only unsubscribe what was subscribed.
- Mirror the same is_synthetic() guard used at subscribe time in teardown code.
- Treat synthetic teardown as state cleanup, not client unsubscribes.
When it happens
Trigger: Calling unsubscribe (UnsubscribeCommand::Instrument) with a synthetic InstrumentId — often during teardown code that unsubscribes everything it ever subscribed, or symmetric subscribe/unsubscribe helpers.
Common situations: Cleanup paths that mirror-subscribe all data types; strategy shutdown code iterating over a mixed list of real and synthetic instrument IDs.
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 unsubscribe from synthetic instrument `InstrumentStat
- Cannot unsubscribe from synthetic instrument `InstrumentClos
- Cannot subscribe for synthetic instrument `Instrument` data
- Cannot subscribe for synthetic instrument `InstrumentStatus`
- Cannot subscribe for synthetic instrument `InstrumentClose`
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b7b240452f8fa32c.
Report an issue: GitHub.