nautechsystems/nautilus_trader · error

invalid Derive orderbook channel `{channel}`

Error message

invalid Derive orderbook channel `{channel}`

What it means

`orderbook_channel_parts` parses a Derive subscription channel name of the form `orderbook.<instrument>.<group>.<depth>`. This error fires when the string has no `orderbook.` prefix, so it cannot be an orderbook channel at all.

Source

Thrown at crates/adapters/derive/src/data.rs:2295

    } else {
        (Some(price), Some(size))
    }
}

fn channel_is_active(
    channels: &AtomicMap<InstrumentId, String>,
    instrument_id: InstrumentId,
    channel: &str,
) -> bool {
    channels
        .get_cloned(&instrument_id)
        .is_some_and(|active_channel| active_channel == channel)
}

fn orderbook_channel_parts(channel: &str) -> anyhow::Result<(String, String, String)> {
    let rest = channel
        .strip_prefix("orderbook.")
        .ok_or_else(|| anyhow::anyhow!("invalid Derive orderbook channel `{channel}`"))?;
    let mut parts = rest.rsplitn(3, '.');
    let depth = parts
        .next()
        .filter(|value| !value.is_empty())
        .ok_or_else(|| anyhow::anyhow!("invalid Derive orderbook channel `{channel}`"))?;
    let group = parts
        .next()
        .filter(|value| !value.is_empty())
        .ok_or_else(|| anyhow::anyhow!("invalid Derive orderbook channel `{channel}`"))?;
    let instrument_name = parts
        .next()
        .filter(|value| !value.is_empty())
        .ok_or_else(|| anyhow::anyhow!("invalid Derive orderbook channel `{channel}`"))?;

    Ok((
        instrument_name.to_string(),
        group.to_string(),
        depth.to_string(),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the channel string starts with `orderbook.`.
  2. Log/print the offending channel to see what was actually passed.
  3. If handling multiple channel kinds, route ticker channels to `ticker_channel_parts` instead.
  4. Check for typos or upstream renames of the channel format.

Example fix

// before
orderbook_channel_parts("ticker.ETH-PERP.100ms")?;

// after
orderbook_channel_parts("orderbook.ETH-PERP.NONE.25")?;
Defensive patterns

Strategy: validation

Validate before calling

if !channel.starts_with("orderbook.") {
    // not an orderbook channel; route elsewhere or skip
}

Type guard

fn is_orderbook_channel(channel: &str) -> bool {
    channel.strip_prefix("orderbook.")
        .map(|r| r.split('.').filter(|s| !s.is_empty()).count() == 3)
        .unwrap_or(false)
}

Try / catch

match orderbook_channel_parts(channel) {
    Ok((instrument, group, depth)) => { /* handle */ }
    Err(e) => tracing::debug!("skipping non-orderbook channel: {e:#}"),
}

Prevention

When it happens

Trigger: Passing a channel string like `ticker.ETH-PERP` or a malformed/renamed channel to the orderbook channel parsing/unsubscription path.

Common situations: Hand-built subscription strings with a typo; a channel recorded under an older naming scheme; passing a ticker channel into an orderbook parser.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/c0fa52925b6a1c25. Report an issue: GitHub.