zeroclaw-labs/zeroclaw · error · anyhow::Error
Mattermost WebSocket ended during authentication
Error message
Mattermost WebSocket ended during authentication
What it means
During WebSocket authentication the read stream returned `None` — the connection ended without a Close frame. The socket vanished silently, which typically means a dropped TCP connection or an intermediary cutting it, rather than a server-initiated close.
Source
Thrown at crates/zeroclaw-channels/src/mattermost.rs:466
Some(Ok(WsMessage::Text(text))) => text,
Some(Ok(WsMessage::Ping(payload))) => {
write
.send(WsMessage::Pong(payload))
.await
.context("Mattermost WebSocket handshake pong failed")?;
continue;
}
Some(Ok(WsMessage::Close(frame))) => {
let reason = frame
.as_ref()
.map(|frame| frame.reason.as_ref())
.unwrap_or("");
bail!("Mattermost WebSocket closed during authentication: {reason}");
}
Some(Err(error)) => {
return Err(error).context("Mattermost WebSocket handshake read failed");
}
None => bail!("Mattermost WebSocket ended during authentication"),
Some(Ok(_)) => continue,
};
let event: serde_json::Value = serde_json::from_str(text.as_ref())
.context("Mattermost WebSocket handshake returned invalid JSON")?;
if let Some(ok) = Self::ws_auth_response(&event, auth_seq) {
if !ok {
bail!("Mattermost WebSocket authentication was rejected");
}
authenticated = true;
}
if event.get("event").and_then(|value| value.as_str()) == Some("hello") {
server_version = Some(
event
.get("data")
.and_then(|data| data.get("server_version"))View on GitHub (pinned to 88bb9c8533)
Solutions
- Retry with backoff — most silent ends during handshake are transient
- Test TCP stability to the Mattermost host (long curl or mtr)
- Check proxy idle-timeout and reset behavior on new WebSocket connections
Defensive patterns
Strategy: retry
Try / catch
Err(e) if e.to_string().contains("ended during authentication") => {
// silent stream end: reconnect with backoff
tokio::time::sleep(backoff.next()).await;
continue;
} Prevention
- Include silent handshake drops in the same reconnect policy as closes
- Track connection failure rates per channel to distinguish environment issues from config issues
- Avoid handshake retries without backoff — rapid reconnect loops can trip server throttling
When it happens
Trigger: During `authenticate_websocket`: network drop, NAT/firewall reset, proxy killing the fresh socket, or the Mattermost process dying before the handshake completes.
Common situations: Flaky networks and VPNs; containers restarting mid-connect; aggressive connection-level firewall rules.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Mattermost WebSocket authentication handshake timed out
- Mattermost WebSocket closed during authentication: {reason}
- Mattermost WebSocket stream ended
- Mattermost WebSocket authentication was rejected
- Mattermost WebSocket closed: {reason}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/64038131aed01f38.
Report an issue: GitHub.