{"record":{"id":"42ffa7fcf2dbac7e","repo":"nautechsystems/nautilus_trader","slug":"invalid-derive-ticker-channel-channel","errorCode":null,"errorMessage":"invalid Derive ticker channel `{channel}`","messagePattern":"invalid Derive ticker channel `(.+?)`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/derive/src/data.rs","lineNumber":2321,"sourceCode":"        .filter(|value| !value.is_empty())\n        .ok_or_else(|| anyhow::anyhow!(\"invalid Derive orderbook channel `{channel}`\"))?;\n    let instrument_name = parts\n        .next()\n        .filter(|value| !value.is_empty())\n        .ok_or_else(|| anyhow::anyhow!(\"invalid Derive orderbook channel `{channel}`\"))?;\n\n    Ok((\n        instrument_name.to_string(),\n        group.to_string(),\n        depth.to_string(),\n    ))\n}\n\nfn ticker_channel_parts(channel: &str) -> anyhow::Result<(String, String)> {\n    let rest = channel\n        .strip_prefix(\"ticker_slim.\")\n        .or_else(|| channel.strip_prefix(\"ticker.\"))\n        .ok_or_else(|| anyhow::anyhow!(\"invalid Derive ticker channel `{channel}`\"))?;\n    let (instrument_name, interval) = rest\n        .rsplit_once('.')\n        .ok_or_else(|| anyhow::anyhow!(\"invalid Derive ticker channel `{channel}`\"))?;\n    anyhow::ensure!(\n        !instrument_name.is_empty() && !interval.is_empty(),\n        \"invalid Derive ticker channel `{channel}`\"\n    );\n\n    Ok((instrument_name.to_string(), interval.to_string()))\n}\n\nfn orderbook_group(params: &Option<Params>) -> anyhow::Result<String> {\n    let group = params\n        .as_ref()\n        .and_then(|p| {\n            p.get_str(\"group\")\n                .map(ToOwned::to_owned)\n                .or_else(|| p.get_u64(\"group\").map(|value| value.to_string()))","sourceCodeStart":2303,"sourceCodeEnd":2339,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/derive/src/data.rs#L2303-L2339","documentation":"`ticker_channel_parts` accepts channels prefixed `ticker_slim.` or `ticker.`. This error fires when the channel has neither prefix, so it cannot be a Derive ticker channel and cannot be split into instrument name and interval.","triggerScenarios":"Passing an orderbook or quote channel string (e.g. `orderbook.ETH-PERP.NONE.25`) into the ticker channel parsing path.","commonSituations":"Mixing channel kinds when unsubscribing from recorded subscriptions; a typo like `tickers.ETH-PERP.100ms`; upstream format changes.","solutions":["Ensure the channel starts with `ticker.` or `ticker_slim.`.","Route orderbook channels to `orderbook_channel_parts` instead.","Log the offending channel string to identify what was passed.","Check for renames/typos in generated subscription names."],"exampleFix":"// before\nticker_channel_parts(\"orderbook.ETH-PERP.NONE.25\")?;\n\n// after\nticker_channel_parts(\"ticker_slim.ETH-PERP.100ms\")?;","handlingStrategy":"validation","validationCode":"if !(channel.starts_with(\"ticker.\") || channel.starts_with(\"ticker_slim.\")) {\n    // route to another parser or skip\n}","typeGuard":"fn is_ticker_channel(channel: &str) -> bool {\n    channel.starts_with(\"ticker.\") || channel.starts_with(\"ticker_slim.\")\n}","tryCatchPattern":"match ticker_channel_parts(channel) {\n    Ok((instrument, interval)) => { /* handle */ }\n    Err(e) => tracing::debug!(\"skipping non-ticker channel: {e:#}\"),\n}","preventionTips":["Dispatch parsing on channel prefix before calling","Avoid typos in channel prefixes","Centralize channel-name construction"],"tags":["derive","websocket","channel","parsing"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}