nautechsystems/nautilus_trader · error
Cannot unsubscribe from synthetic instrument `OptionGreeks`
Error message
Cannot unsubscribe from synthetic instrument `OptionGreeks` data
What it means
The DataEngine rejects unsubscribing from OptionGreeks data for a synthetic instrument ID. OptionGreeks streams for synthetic instruments are computed locally, so no downstream client subscription exists and the unsubscribe command is invalid.
Source
Thrown at crates/data/src/engine/mod.rs:1284
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()) {
client.execute_unsubscribe(cmd);
} else {
log::error!(
"Cannot handle command: no client found for client_id={:?}, venue={:?}",
cmd.client_id(),
cmd.venue(),
);
}
Ok(())
}
/// Sends a [`RequestCommand`] to a suitable data client implementation.View on GitHub (pinned to 18893faf8b)
Solutions
- Skip the unsubscribe call for synthetic instrument IDs (synthetic greeks are engine-computed)
- Check instrument_id.is_synthetic() before constructing the OptionGreeks unsubscribe command
- Use a real exchange-listed option instrument ID when unsubscribing from venue greeks data
- Manage synthetic greeks lifecycle through the SyntheticInstrument API instead
Example fix
// before
for id in active_ids {
engine.unsubscribe(OptionGreeks::new(id, client_id, venue));
}
// after
for id in active_ids.into_iter().filter(|id| !id.is_synthetic()) {
engine.unsubscribe(OptionGreeks::new(id, client_id, venue));
} Defensive patterns
Strategy: validation
Validate before calling
if instrument_id.is_synthetic() {
return Ok(()); // synthetic greeks lifecycle is engine-managed
} Type guard
fn is_venue_instrument(id: &InstrumentId) -> bool {
!id.is_synthetic()
} Try / catch
if let Err(e) = engine.unsubscribe(cmd) {
if e.to_string().contains("synthetic") { log::debug!("ignoring: {e}"); }
else { return Err(e); }
} Prevention
- Filter synthetic IDs out of bulk unsubscribe loops
- Use SyntheticInstrument drop/cancel APIs for synthetic greeks
- Validate instrument IDs at config load time
When it happens
Trigger: Calling DataEngine.unsubscribe with UnsubscribeCommand::OptionGreeks where cmd.instrument_id.is_synthetic() is true — i.e. an ID minted by SyntheticInstrument rather than a venue-listed option ID.
Common situations: Passing a synthetic option ID built from a synthetic underlying into greeks subscription management; generic unsubscribe loops that iterate all active subscriptions including synthetic ones.
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/cf0a6e5697191ee4.
Report an issue: GitHub.