zeroclaw-labs/zeroclaw · error · anyhow::Error
Mattermost WebSocket closed: {reason}
Error message
Mattermost WebSocket closed: {reason} What it means
The server sent a WebSocket Close frame during an established listening session; the reason string is included. This is the normal shutdown path for the protocol: server restarts, session invalidation, or proxy closes. The error exists so the listener can distinguish close-with-reason from silent drops and reconnect.
Source
Thrown at crates/zeroclaw-channels/src/mattermost.rs:1076
}
None => bail!("Mattermost WebSocket stream ended"),
};
let text = match frame {
WsMessage::Text(text) => text,
WsMessage::Ping(payload) => {
write
.send(WsMessage::Pong(payload))
.await
.context("Mattermost WebSocket pong send failed")?;
continue;
}
WsMessage::Close(frame) => {
let reason = frame
.as_ref()
.map(|frame| frame.reason.as_ref())
.unwrap_or("");
bail!("Mattermost WebSocket closed: {reason}");
}
_ => continue,
};
let event: serde_json::Value = match serde_json::from_str(text.as_ref()) {
Ok(event) => event,
Err(error) => {
::zeroclaw_log::record!(
WARN,
::zeroclaw_log::Event::new(
module_path!(),
::zeroclaw_log::Action::Note,
)
.with_outcome(::zeroclaw_log::EventOutcome::Unknown)
.with_attrs(::serde_json::json!({
"alias": self.alias,
"error": error.to_string(),
})),View on GitHub (pinned to 88bb9c8533)
Solutions
- Treat as reconnectable: re-invoke `listen()` with backoff
- Inspect the close reason — auth-policy closes need a token refresh, not a retry
- If closes repeat rapidly, check server health and token validity
Defensive patterns
Strategy: retry
Try / catch
match mm_channel.listen(tx).await {
Err(e) if e.to_string().contains("Mattermost WebSocket closed:") => {
let reason = e.to_string();
if reason.contains("auth") {
// refresh credentials before reconnecting
}
// otherwise reconnect with backoff
}
other => other,
} Prevention
- Treat Close frames as normal lifecycle events: log the reason, reconnect
- Only escalate when closes recur faster than a backoff floor
- Preserve the close reason in logs — it distinguishes restarts from policy closes
When it happens
Trigger: `listen_websocket` receives `WsMessage::Close` mid-session: Mattermost shutdown/restart, server-side token/session invalidation, or an intermediary closing the connection.
Common situations: Server upgrades and nightly restarts; token revoked causing the server to close all its sockets; proxy idle closes.
Related errors
- Mattermost WebSocket closed during authentication: {reason}
- Mattermost WebSocket authentication handshake timed out
- Mattermost WebSocket ended during authentication
- Mattermost WebSocket authentication was rejected
- Mattermost WebSocket stream ended
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/5064d7b50633aa28.
Report an issue: GitHub.