nautechsystems/nautilus_trader · error
instrument ID `{instrument_id}` is not for venue {}
Error message
instrument ID `{instrument_id}` is not for venue {} What it means
Derive adapter's currency_from_instrument_id helper only accepts instrument IDs belonging to the Derive venue. If the caller passes an instrument ID minted for a different venue (or with a malformed venue portion), the ensure! macro aborts with this message naming the offending ID and the expected venue. It is a guard against silently deriving a currency from a non-Derive instrument.
Source
Thrown at crates/adapters/derive/src/data.rs:2397
fn trade_channel(instrument: &InstrumentAny) -> anyhow::Result<String> {
let instrument_type = derive_instrument_type(instrument)?.to_string();
let instrument_id = instrument.id();
let currency = currency_from_instrument_id(&instrument_id)?;
Ok(trades_channel(&instrument_type, currency))
}
fn derive_instrument_type(instrument: &InstrumentAny) -> anyhow::Result<DeriveInstrumentType> {
match instrument {
InstrumentAny::CryptoPerpetual(_) => Ok(DeriveInstrumentType::Perp),
InstrumentAny::CryptoOption(_) => Ok(DeriveInstrumentType::Option),
InstrumentAny::CurrencyPair(_) => Ok(DeriveInstrumentType::Erc20),
other => anyhow::bail!("unsupported Derive instrument type for trades: {other:?}"),
}
}
fn currency_from_instrument_id(instrument_id: &InstrumentId) -> anyhow::Result<&str> {
anyhow::ensure!(
instrument_id.venue == *DERIVE_VENUE,
"instrument ID `{instrument_id}` is not for venue {}",
DERIVE_VENUE.as_str(),
);
instrument_id
.symbol
.as_str()
.split_once('-')
.and_then(|(currency, _)| (!currency.is_empty()).then_some(currency))
.ok_or_else(|| anyhow::anyhow!("cannot derive currency from {instrument_id}"))
}
// Caps the rendered JSON at ~512 bytes for log grep-ability and backs the
// slice off to a UTF-8 char boundary so a multi-byte codepoint near the cap
// can never produce a panicking slice.
fn truncated_payload_snippet(raw: &str) -> String {
const MAX_LEN: usize = 512;View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the InstrumentId passed to Derive calls was created for the Derive venue (use the adapter's DERIVE_VENUE constant or its instrument-ID parsing helper).
- Verify the venue portion of the ID string matches Derive exactly (case/format as defined by DERIVE_VENUE).
- If handling multiple venues, filter or dispatch instrument IDs by venue before reaching the Derive client.
- Log the full instrument ID and expected venue to find where the cross-venue ID leaked in.
Example fix
// before
let id = InstrumentId::from("ETH-PERP.BINANCE");
derive_client.currency_from_instrument_id(&id)?;
// after
let id = InstrumentId::from("ETH-PERP.DERIVE");
derive_client.currency_from_instrument_id(&id)?; Defensive patterns
Strategy: validation
Validate before calling
fn ensure_derive_instrument(id: &InstrumentId) -> Result<(), String> {
if id.venue.as_str() != DERIVE_VENUE.as_str() {
return Err(format!("{} is not a Derive instrument (venue {})", id, id.venue));
}
Ok(())
} Type guard
fn is_derive_instrument(id: &InstrumentId) -> bool {
id.venue == *DERIVE_VENUE
} Try / catch
match derive_client.currency_from_instrument_id(&id) {
Ok(cur) => /* use currency */,
Err(e) => log::warn!("skip non-Derive instrument: {e}"),
} Prevention
- Only route Derive-venue instrument IDs into Derive client calls
- Dispatch by venue before calling adapter-specific helpers
- Derive instrument IDs from the adapter's instrument provider, not hand-built strings
When it happens
Trigger: Calling Derive data/execution code paths that resolve a currency (e.g. to build request parameters) with an InstrumentId whose venue != Derive, such as passing a Binance instrument ID into a Derive API call, or constructing an InstrumentId manually with a typo'd venue string.
Common situations: Routing logic that forwards instrument IDs from a multi-venue portfolio into Derive-specific helpers; copy-pasted instrument IDs in config or test fixtures; venue string casing mistakes when parsing user input.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- cannot derive currency from {instrument_id}
- {FAILED}: {e}
- unsupported order type for Derive: {other:?}
- unsupported trigger order type for Derive: {other:?}; suppor
- unsupported trigger price type for Derive: IndexPrice; Deriv
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/70b06974d690b292.
Report an issue: GitHub.