{"record":{"id":"f249d8b7b8c44a9a","repo":"nautechsystems/nautilus_trader","slug":"subscribe-user-requires-a-user-channel-client-c","errorCode":null,"errorMessage":"subscribe_user() requires a user-channel client (created with new_user())","messagePattern":"subscribe_user\\(\\) requires a user-channel client \\(created with new_user\\(\\)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/websocket/client.rs","lineNumber":562,"sourceCode":"            anyhow::bail!(\n                \"unsubscribe_market() requires a market-channel client (created with new_market())\"\n            );\n        }\n        self.cmd_tx\n            .read()\n            .await\n            .send(HandlerCommand::UnsubscribeMarket(asset_ids))\n            .map_err(|e| anyhow::anyhow!(\"Failed to send UnsubscribeMarket: {e}\"))\n    }\n\n    /// Authenticate and subscribe to the user channel.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if called on a market-channel client (no credentials available).\n    pub async fn subscribe_user(&self) -> anyhow::Result<()> {\n        if self.channel != WsChannel::User {\n            anyhow::bail!(\n                \"subscribe_user() requires a user-channel client (created with new_user())\"\n            );\n        }\n        self.cmd_tx\n            .read()\n            .await\n            .send(HandlerCommand::SubscribeUser)\n            .map_err(|e| anyhow::anyhow!(\"Failed to send SubscribeUser: {e}\"))?;\n        // Set only after the command is successfully enqueued so a failed send does not\n        // leave user_subscribed=true and cause an unintended replay on the next connect().\n        self.user_subscribed.store(true, Ordering::Relaxed);\n        Ok(())\n    }\n\n    /// Returns a cloneable subscription handle for use in spawned tasks.\n    #[must_use]\n    pub fn clone_subscription_handle(&self) -> WsSubscriptionHandle {\n        WsSubscriptionHandle {","sourceCodeStart":544,"sourceCodeEnd":580,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/websocket/client.rs#L544-L580","documentation":"subscribe_user sends authenticated subscription commands derived from stored API credentials and is only valid on a client configured for the user channel (new_user). A market-channel client has no credentials, so the call cannot work and is rejected.","triggerScenarios":"Calling subscribe_user() on a client built with new_market() (WsChannel::Market), e.g. expecting order/fill updates from a book-data connection.","commonSituations":"Using one shared market-data client to also receive private order events; forgetting that Polymarket requires a separate authenticated user-channel connection with API keys.","solutions":["Build the client with PolymarketWebSocketClient::new_user() with valid API credentials, then call subscribe_user()","Maintain two clients: new_market() for books and new_user() for order/fill updates","Check the channel before subscribing"],"exampleFix":"// before\nlet client = PolymarketWebSocketClient::new_market().await?;\nclient.subscribe_user().await?;\n// after\nlet client = PolymarketWebSocketClient::new_user(api_creds).await?;\nclient.subscribe_user().await?;","handlingStrategy":"validation","validationCode":"if client.channel() == WsChannel::User {\n    client.subscribe_user().await?;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Create a dedicated new_user() client with valid API credentials for private events","Do not expect fill/order updates from market-channel connections"],"tags":["rust","websocket","polymarket","channel-mismatch"],"backgroundTag":"invalid-state-transition","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"}