nautechsystems/nautilus_trader · error
subscribe_user() requires a user-channel client (created wit
Error message
subscribe_user() requires a user-channel client (created with new_user())
What it means
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.
Source
Thrown at crates/adapters/polymarket/src/websocket/client.rs:562
anyhow::bail!(
"unsubscribe_market() requires a market-channel client (created with new_market())"
);
}
self.cmd_tx
.read()
.await
.send(HandlerCommand::UnsubscribeMarket(asset_ids))
.map_err(|e| anyhow::anyhow!("Failed to send UnsubscribeMarket: {e}"))
}
/// Authenticate and subscribe to the user channel.
///
/// # Errors
///
/// Returns an error if called on a market-channel client (no credentials available).
pub async fn subscribe_user(&self) -> anyhow::Result<()> {
if self.channel != WsChannel::User {
anyhow::bail!(
"subscribe_user() requires a user-channel client (created with new_user())"
);
}
self.cmd_tx
.read()
.await
.send(HandlerCommand::SubscribeUser)
.map_err(|e| anyhow::anyhow!("Failed to send SubscribeUser: {e}"))?;
// Set only after the command is successfully enqueued so a failed send does not
// leave user_subscribed=true and cause an unintended replay on the next connect().
self.user_subscribed.store(true, Ordering::Relaxed);
Ok(())
}
/// Returns a cloneable subscription handle for use in spawned tasks.
#[must_use]
pub fn clone_subscription_handle(&self) -> WsSubscriptionHandle {
WsSubscriptionHandle {View on GitHub (pinned to 18893faf8b)
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
Example fix
// before let client = PolymarketWebSocketClient::new_market().await?; client.subscribe_user().await?; // after let client = PolymarketWebSocketClient::new_user(api_creds).await?; client.subscribe_user().await?;
Defensive patterns
Strategy: validation
Validate before calling
if client.channel() == WsChannel::User {
client.subscribe_user().await?;
} Prevention
- Create a dedicated new_user() client with valid API credentials for private events
- Do not expect fill/order updates from market-channel connections
When it happens
Trigger: Calling subscribe_user() on a client built with new_market() (WsChannel::Market), e.g. expecting order/fill updates from a book-data connection.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- subscribe_market() requires a market-channel client (created
- unsubscribe_market() requires a market-channel client (creat
- conflicting RTDS TWAP observation topic={} symbol={} timesta
- Unsupported RTDS custom data type: {other}
- Failed to start Polymarket WebSocket handler task: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f249d8b7b8c44a9a.
Report an issue: GitHub.