nautechsystems/nautilus_trader · error
unsubscribe_market() requires a market-channel client (creat
Error message
unsubscribe_market() requires a market-channel client (created with new_market())
What it means
unsubscribe_market sends a market-channel unsubscribe command and is only valid on a client configured for the market channel. On a user-channel client there is no asset-id market subscription to remove, so the call is rejected up front.
Source
Thrown at crates/adapters/polymarket/src/websocket/client.rs:544
}
self.cmd_tx
.read()
.await
.send(HandlerCommand::SubscribeMarket(asset_ids))
.map_err(|e| anyhow::anyhow!("Failed to send SubscribeMarket: {e}"))
}
/// Remove asset IDs from the active subscription set.
///
/// The IDs are dropped from the reconnect set so they will not be
/// re-subscribed after a reconnect. No wire message is sent.
///
/// # Errors
///
/// Returns an error if called on a user-channel client (incompatible channel).
pub async fn unsubscribe_market(&self, asset_ids: Vec<String>) -> anyhow::Result<()> {
if self.channel != WsChannel::Market {
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!(View on GitHub (pinned to 18893faf8b)
Solutions
- Only call unsubscribe_market on clients created with new_market(); use unsubscribe_user for user-channel clients
- Track the channel of each client and branch teardown logic on it
- Check the channel field before calling to avoid the error
Example fix
// before
client.unsubscribe_market(asset_ids).await?;
client.unsubscribe_user().await?;
// after
match client.channel() {
WsChannel::Market => client.unsubscribe_market(asset_ids).await?,
WsChannel::User => client.unsubscribe_user().await?,
} Defensive patterns
Strategy: validation
Validate before calling
if client.channel() == WsChannel::Market {
client.unsubscribe_market(asset_ids).await?;
} Prevention
- Branch teardown logic on the client's channel
- Only unsubscribe what you actually subscribed on that client
When it happens
Trigger: Calling unsubscribe_market(asset_ids) on a client built with new_user() (WsChannel::User), typically to tear down subscriptions that were never made on that client.
Common situations: Cleanup/shutdown code that calls both unsubscribe_market and unsubscribe_user on every client regardless of channel; wrong client instance passed to a teardown helper.
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
- subscribe_user() requires a user-channel client (created wit
- 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/621dc1c3a4980850.
Report an issue: GitHub.