{"record":{"id":"ec37043199a32b61","repo":"nautechsystems/nautilus_trader","slug":"not-a-subscription-channel-kind","errorCode":null,"errorMessage":"Not a subscription channel: {kind}","messagePattern":"Not a subscription channel: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/websocket/client.rs","lineNumber":2409,"sourceCode":"            })\n        }\n        HyperliquidWsChannel::UserTwapSliceFills => Ok(SubscriptionRequest::UserTwapSliceFills {\n            user: rest.context(\"Missing user\")?.to_string(),\n        }),\n        HyperliquidWsChannel::UserTwapHistory => Ok(SubscriptionRequest::UserTwapHistory {\n            user: rest.context(\"Missing user\")?.to_string(),\n        }),\n        HyperliquidWsChannel::Bbo => Ok(SubscriptionRequest::Bbo {\n            coin: Ustr::from(rest.context(\"Missing coin\")?),\n        }),\n\n        // Response-only channels are not valid subscription topics\n        HyperliquidWsChannel::SubscriptionResponse\n        | HyperliquidWsChannel::User\n        | HyperliquidWsChannel::Post\n        | HyperliquidWsChannel::Pong\n        | HyperliquidWsChannel::Error => {\n            anyhow::bail!(\"Not a subscription channel: {kind}\")\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use nautilus_live::{SocketReconnectRegistry, SocketReconnectRequestOutcome};\n    use nautilus_model::identifiers::ClientId;\n    use nautilus_network::mode::ReconnectRequestOutcome;\n    use rstest::rstest;\n    use ustr::Ustr;\n\n    use super::*;\n    use crate::{\n        common::{\n            consts::{HYPERLIQUID_WS_POST_INFLIGHT_MAX, HYPERLIQUID_WS_SUBSCRIPTIONS_MAX},\n            enums::HyperliquidBarInterval,\n        },","sourceCodeStart":2391,"sourceCodeEnd":2427,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/websocket/client.rs#L2391-L2427","documentation":"The Hyperliquid WebSocket adapter validates that the requested channel kind can actually be subscribed to. Response-only channels — SubscriptionResponse, User, Post, Pong, and Error — are message categories the server sends, not topics a client can subscribe to, so passing any of them to the subscription-topic conversion bails with this error. It is a fail-fast guard preventing an invalid subscription request from being sent.","triggerScenarios":"Calling the subscribe API (or building a HyperliquidSubscription) with channel = SubscriptionResponse, User, Post, Pong, or Error. Typically happens when code maps a generic channel enum or a user-supplied string into HyperliquidWsChannel without filtering response-only variants.","commonSituations":"Constructing subscriptions from parsed config where the channel string resolves to a response-only variant; writing generic routing code that forwards every channel enum to subscribe; typos or misunderstanding of which Hyperliquid channels are subscribable vs. reply-only.","solutions":["Use a valid subscription channel (e.g. trades, l2Book, allMids, candle, userEvents) instead of the response-only variant.","Add a whitelist/filter before subscribing that rejects SubscriptionResponse, User, Post, Pong, and Error.","If the channel comes from user config, validate/parse it into a dedicated subscribable-channels enum at config-load time."],"exampleFix":"// before\nlet channel: HyperliquidWsChannel = value.parse()?;\nclient.subscribe(channel, args).await?;\n// after\nlet channel: HyperliquidWsChannel = value.parse()?;\nif !matches!(channel,\n    HyperliquidWsChannel::SubscriptionResponse\n    | HyperliquidWsChannel::User\n    | HyperliquidWsChannel::Post\n    | HyperliquidWsChannel::Pong\n    | HyperliquidWsChannel::Error)\n{\n    client.subscribe(channel, args).await?;\n}","handlingStrategy":"validation","validationCode":"const SUBSCRIBABLE: &[HyperliquidWsChannel] = &[\n    HyperliquidWsChannel::Trades,\n    HyperliquidWsChannel::L2Book,\n    HyperliquidWsChannel::AllMids,\n    HyperliquidWsChannel::Candle,\n];\nfn is_subscribable(ch: &HyperliquidWsChannel) -> bool {\n    SUBSCRIBABLE.contains(ch)\n}","typeGuard":"fn is_response_only(ch: &HyperliquidWsChannel) -> bool {\n    matches!(ch,\n        HyperliquidWsChannel::SubscriptionResponse\n        | HyperliquidWsChannel::User\n        | HyperliquidWsChannel::Post\n        | HyperliquidWsChannel::Pong\n        | HyperliquidWsChannel::Error)\n}","tryCatchPattern":null,"preventionTips":["Keep config channel strings limited to the documented subscribable channels","Parse user/config channel names through a dedicated subscribable-channels parser","Unit-test subscription construction against a whitelist of valid channels"],"tags":["websocket","rust","hyperliquid","enum","validation"],"backgroundTag":"unsupported-enum-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}