moeru-ai/airi · error · Error
No candidate server channel URL was reachable. ${errors.join
Error message
No candidate server channel URL was reachable. ${errors.join('; ')} What it means
Thrown by probeServerChannelQrPayload after every candidate URL in payload.urls failed its websocket handshake/connect probe. Each per-URL failure is captured via errorMessageFrom and aggregated into the message joined by '; '. The host bridge is present (errors [0]/[1] did not fire), but no URL produced a working connection within the 2.5s connect timeout.
Source
Thrown at apps/stage-pocket/src/modules/server-channel-qr-probe.ts:42
connectTimeoutMs: 2_000,
name: WebSocketEventSource.StageWeb,
token: payload.authToken,
url,
connector: createTextProtocolConnector(connector),
})
try {
await client.connect({ timeout: 2_500 })
client.close()
return url
}
catch (error) {
client.close()
errors.push(`${url}: ${errorMessageFrom(error) ?? 'Unknown websocket probe error'}`)
}
}
throw new Error(`No candidate server channel URL was reachable. ${errors.join('; ')}`)
}
View on GitHub (pinned to 27111382b4)
Solutions
- Read the aggregated per-URL reasons in the message to identify whether the failure is connection-refused, timeout, TLS, or auth.
- Ensure the desktop AIRI app is running and its server-channel service is started, and confirm the advertised host:port matches the phone's reachable network path.
- Verify both devices are on the same LAN/subnet and that the server-channel port (default 6121) is not firewalled.
- For wss URLs, install/trust the desktop's generated certificate on the mobile device, or disable TLS for local testing.
- Re-scan the QR if the authToken may have rotated.
Defensive patterns
Strategy: retry
Try / catch
try {
await probeServerChannelQrPayload(payload)
}
catch (error) {
const msg = errorMessageFrom(error) ?? ''
if (msg.startsWith('No candidate server channel URL was reachable.')) {
// parse the per-URL reasons, guide the user (start desktop, check LAN, trust cert)
}
throw error
} Prevention
- Ensure the desktop AIRI server-channel is started before scanning the QR.
- Confirm phone and desktop share a LAN subnet and the server-channel port is open.
- Trust the desktop's self-signed cert on the mobile device for wss URLs.
- Re-scan the QR if the desktop restarted (authToken may have rotated).
When it happens
Trigger: The QR payload lists one or more ws/wss URLs and client.connect({ timeout: 2_500 }) rejected for each — causes include the desktop server channel not running, wrong port, firewall blocking the LAN IP, TLS/cert mismatch on wss, expired/invalid authToken, or the host not bound on the advertised interface.
Common situations: Desktop AIRI app not running or server-channel service not started; phone on a different subnet than the desktop; port 6121 blocked by firewall; wss URL with a self-signed cert the webview rejects; authToken in the QR no longer valid after a desktop restart; IPv6 link-local address advertised without zone id.
Related errors
- AIRI host websocket bridge is unavailable
- AIRI host websocket bridge is unavailable
- No reachable private LAN address is available for the curren
- Token exchange failed (${response.status}): ${text}
- Failed to apply server channel configuration
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/09e1248b53334cc0.
Report an issue: GitHub.