nautechsystems/nautilus_trader · error · anyhow::Error
Failed to send SubscribeUser: {e}
Error message
Failed to send SubscribeUser: {e} What it means
subscribe_user() sends HandlerCommand::SubscribeUser to the feed-handler task to authenticate and open the private user channel. The send fails when the handler's receiver was dropped — the handler task has exited, so no session exists for the authenticated subscription. Note the flag user_subscribed is only set after a successful send, precisely to avoid replaying a subscription that never got enqueued.
Source
Thrown at crates/adapters/polymarket/src/websocket/client.rs:570
.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 {
cmd_tx: Arc::clone(&self.cmd_tx),
}
}
/// Takes the message receiver, leaving `None` in its place.
///
/// This is useful when the data client needs to spawn its own handler
/// task that reads messages independently of the WS client.View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the client is connected (is_active()) and call connect() first if not
- Retry subscribe_user() after reconnecting; the user subscription is replayed on reconnect once user_subscribed=true
- Fix the root cause of the handler's exit (check wrapped error in logs, refresh auth credentials)
- Serialize lifecycle calls (connect/subscribe/disconnect) to avoid races
Example fix
// before
client.subscribe_user().await?;
// after
if !client.is_active() {
client.connect().await?;
}
client.subscribe_user().await?; Defensive patterns
Strategy: try-catch
Validate before calling
if !client.is_active() {
client.connect().await?;
}
// credentials must be present for the user channel
debug_assert!(!api_key.is_empty(), "user channel requires credentials"); Try / catch
match client.subscribe_user().await {
Err(e) if e.to_string().contains("Failed to send SubscribeUser") => {
client.connect().await?;
client.subscribe_user().await?;
}
other => other?,
} Prevention
- Check is_active() before enabling the user channel
- Ensure the handler task is healthy (it exits on fatal connection/auth errors) before subscribing
- Keep credentials valid — handler startup auth failures kill the task that would receive this command
- Call subscribe_user() only after a successful connect(), never concurrently with disconnect
When it happens
Trigger: Calling subscribe_user() after disconnect(), after the handler task died (connection loss, panic, auth startup failure), or during a concurrent reconnect.
Common situations: Enabling the private order/fill feed while the gateway is down; credentials problems killed the handler earlier; shutdown racing an in-flight subscribe_user() from another task.
Related errors
- Failed to send SubscribeMarket: {e}
- Failed to send UnsubscribeMarket: {e}
- Failed to replay SubscribeUser: {e}
- Failed to send SetClient command: {e}
- unsupported Derive public WS channel `{}`
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a3d6e9693530d9cf.
Report an issue: GitHub.