zeroclaw-labs/zeroclaw · error · anyhow::Error
Mattermost WebSocket authentication was rejected
Error message
Mattermost WebSocket authentication was rejected
What it means
The Mattermost WebSocket handshake completed, and the server explicitly answered the auth challenge (`ws_auth_response` matched the auth sequence) with a rejection. This is a credential refusal over WebSocket — almost always an invalid, expired, or revoked token.
Source
Thrown at crates/zeroclaw-channels/src/mattermost.rs:475
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"))
.and_then(|value| value.as_str())
.unwrap_or("unknown")
.to_string(),
);
}
}
}
}
}View on GitHub (pinned to 88bb9c8533)
Solutions
- Regenerate the personal access token and update `bot_token` in config
- If using login_id/password, verify those credentials via REST login first
- Sanity-check the token: `curl -H "Authorization: Bearer <token>" <server>/api/v4/users/me` must return the bot user
Defensive patterns
Strategy: try-catch
Validate before calling
let resp = client
.get(format!("{base_url}/api/v4/users/me"))
.bearer_auth(&token)
.send()
.await?;
if !resp.status().is_success() {
return Err(anyhow::anyhow!("token rejected; refresh before starting WS listen"));
} Try / catch
match mm_channel.listen(tx).await {
Err(e) if e.to_string().contains("authentication was rejected") => {
// fatal credential problem: refresh bot_token / re-login, then reconnect
}
other => other,
} Prevention
- Pre-validate the token over REST before starting the WebSocket listener
- Rotate tokens proactively and alert on auth rejections — retrying with a bad token cannot succeed
- Keep token generation scripted so refreshes update config in one step
When it happens
Trigger: `listen_websocket` authenticating with a bot_token or password-derived session token that the server refuses: revoked personal access token, expired login session, or a token from a different instance.
Common situations: Personal access token regenerated in Mattermost but config still holds the old one; session token invalidated by logout/password change; token copied with extra characters.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- GET /users/me/channels returned {}
- login failed ({status}): {body}
- Mattermost WebSocket authentication handshake timed out
- Mattermost WebSocket closed during authentication: {reason}
- Mattermost WebSocket ended during authentication
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/00cb1ac69307bb36.
Report an issue: GitHub.