moeru-ai/airi · error
WebSocket server connection failed
Error message
WebSocket server connection failed
What it means
The channel server store's WebSocket client (server SDK Client) reached its terminal 'failed' state: authentication failed terminally, the reconnect retry budget was exhausted, or autoReconnect is disabled. connected is set to false and the initializing lock is cleared so a fresh initialize() can build a new client. This is stronger than onClose (runtime disconnect, SDK keeps auto-reconnecting) - after 'failed', nothing retries on its own.
Source
Thrown at packages/stage-ui/src/stores/mods/api/channel-server.ts:190
connected.value = false
if (!hasEverConnected.value) {
// First handshake failed: clear lock so initialize() can be retried externally.
initializing.value = null
}
// Runtime disconnect: keep initialize/listeners for SDK auto-reconnect.
// Terminal failure: handled by onStateChange status === 'failed'.
},
onStateChange: ({ status }) => {
if (attempt !== connectionAttempt)
return
if (status === 'failed') {
// SDK entered terminal state (auth terminal / retries exhausted / autoReconnect disabled).
connected.value = false
initializing.value = null
console.warn('WebSocket server connection failed')
}
},
onReady: () => {
if (attempt !== connectionAttempt)
return
const isReconnect = hasEverConnected.value
hasEverConnected.value = true
connected.value = true
flush()
initializeListeners()
if (isReconnect) {
for (const callback of reconnectedCallbacks) {
try {
callback()
}View on GitHub (pinned to 677329427f)
Solutions
- Verify the WebSocket server URL setting and reachability (connect manually with a ws client to the same URL)
- Re-authenticate to obtain a fresh token, then call initialize() again - the cleared lock exists exactly to allow this
- Check server logs for repeated auth failures or handshake rejections from this client
- If retries were exhausted by a transient outage, simply call initialize() once the server is back
- Confirm autoReconnect is enabled in the client options if automatic recovery is expected
Example fix
// before: one-shot init, no retry after terminal failure
await channelServer.initialize()
// after: re-arm with backoff when the SDK gives up
watch(connected, (isConnected, wasConnected) => {
if (wasConnected && !isConnected && !initializing.value)
retryWithBackoff(() => channelServer.initialize())
}) Defensive patterns
Strategy: retry
Validate before calling
if (!websocketUrl.value || !token)
throw new Error('WebSocket server URL and auth token are required')
await channelServer.initialize() Try / catch
watch(connected, (isConnected, wasConnected) => {
if (wasConnected && !isConnected && !initializing.value)
retryWithBackoff(() => channelServer.initialize())
}) Prevention
- Refresh auth tokens proactively before they expire
- Validate the ws/wss URL scheme and reachability before connecting
- Watch the connected ref and re-arm initialize() after terminal 'failed' states - the SDK will not retry on its own
- Keep autoReconnect enabled unless you own the retry loop
When it happens
Trigger: Handshake rejected with 401/403 due to a wrong or expired token; websocketUrl pointing at a dead or wrong endpoint until retries exhaust; autoReconnect disabled in client options; server-side auth marking the session terminal.
Common situations: Expired auth token after long idle; wrong server URL in settings; reverse proxy dropping WebSocket upgrades so every attempt fails; token audience mismatch after server updates.
Related errors
- Client is not connected, current status: ${this.status}
- No WebSocket constructor is available. Pass `wsConstructor`
- WebSocket transport is not implemented for node runtime yet.
- WebSocket transport is not implemented for web runtime yet.
- Invalid WebSocket event format.
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/f74100b17137a6d9.
Report an issue: GitHub.