moghtech/komodo · warning
Cancelled before receive
Error message
Cancelled before receive
What it means
In lib/transport/src/websocket/tungstenite.rs recv, the read is raced against a cancellation token; if the token is cancelled before the next WebSocket message arrives, the function aborts the pending read and returns 'Cancelled before receive'. This is deliberate cooperative cancellation of a blocking receive, not a socket failure.
Solutions
- Handle this variant as a normal shutdown signal: exit the receive loop cleanly without treating it as a transport failure.
- If unexpected, audit who calls cancel() on the token (reconnect logic, shutdown hooks) and whether it fires too early.
- Ensure the pending read is not expected to complete after cancellation; re-issue recv on a fresh connection if work must continue.
- Distinguish cancellation errors from network errors when logging/metrics to avoid false alarms.
Example fix
// before
let msg = ws.recv().await?;
// after
match ws.recv().await {
Ok(msg) => handle(msg),
Err(e) if e.to_string() == "Cancelled before receive" => break, // shutdown, not an error
Err(e) => return Err(e),
} Defensive patterns
Strategy: try-catch
Type guard
fn is_cancelled(err: &anyhow::Error) -> bool { err.to_string() == "Cancelled before receive" } Try / catch
match ws.recv().await {
Ok(m) => handle(m),
Err(e) if e.to_string() == "Cancelled before receive" => break Ok(()), // expected shutdown
Err(e) => break Err(e),
} Prevention
- Treat cancellation as a control-flow signal, not a failure; branch on the message before logging as error.
- Centralize who owns the CancellationToken and document when cancel() fires.
- Avoid cancelling while a critical read/replay is in flight; cancel only at safe points.
- In tests, assert this variant is produced on shutdown to keep reconnect logic honest.
When it happens
Trigger: Shutting down a task/connection while recv is (or is about to be) waiting: dropping the runtime actor, calling cancel() on the shared CancellationToken, or a supervisor aborting the connection during teardown or reconnect.
Common situations: Graceful shutdown of a service holding an open WebSocket; reconnect logic cancelling the old connection's receive loop; tests or timeouts cancelling long-idle reads.
Related errors
- Failed to log in |
- Socket closed before login
- Connection closed
- Connection already closed
- Invalid ssl key file path.
AI-assisted analysis of moghtech/komodo@780ac68b99 (2026-09-08).
Data as JSON: /api/errors/a33d5e3daba57673.
Report an issue: GitHub.
Appendix: source
Thrown at lib/transport/src/websocket/tungstenite.rs:164
receiver,
cancel: None,
}
}
}
impl WebsocketReceiver for TungsteniteWebsocketReceiver {
type CloseFrame = CloseFrame;
fn set_cancel(&mut self, cancel: CancellationToken) {
self.cancel = Some(cancel);
}
async fn recv(&mut self) -> anyhow::Result<WebsocketMessage> {
let fut = try_next(&mut self.receiver);
if let Some(cancel) = &self.cancel {
tokio::select! {
res = fut => res,
_ = cancel.cancelled() => Err(anyhow!("Cancelled before receive"))
}
} else {
fut.await
}
}
}
impl TungsteniteWebsocket {
pub async fn connect_maybe_tls_insecure(
url: &str,
insecure: bool,
) -> mogh_error::Result<(Self, HeaderValue)> {
if insecure {
Self::connect_tls_insecure(url).await
} else {
Self::connect(url).await
}
}View on GitHub (pinned to 780ac68b99)