moeru-ai/airi · error · Error
No WebSocket constructor is available. Pass `wsConstructor`…
Error message
No WebSocket constructor is available. Pass `wsConstructor` or use a connector.
What it means
better-ws's built-in socket connector needs a WebSocket constructor: it uses options.wsConstructor when provided, otherwise globalThis.WebSocket. When neither exists — typical for Node.js where the global is absent or experimental — connect() throws this error telling you to pass wsConstructor or bring your own ClientConnector.
Solutions
- Install the ws package and pass it: createClient({ url, wsConstructor: WebSocket }) with import WebSocket from 'ws'
- Or run on Node 22+ where globalThis.WebSocket is available and enabled
- Or supply a custom ClientConnector via the connector option to fully own the transport (also needed for binary frames, since the built-in connector is text-only)
Example fix
// before
const client = createClient({ url: 'ws://localhost:3000' }) // Node: Error: No WebSocket constructor is available...
// after
import WebSocket from 'ws'
const client = createClient({ url: 'ws://localhost:3000', wsConstructor: WebSocket }) Defensive patterns
Strategy: validation
Validate before calling
// Resolve a constructor before creating the client
const wsConstructor = globalThis.WebSocket
?? (await import('ws')).default
if (!wsConstructor)
throw new Error('No WebSocket implementation available in this runtime')
const client = createClient({ url, wsConstructor }) Prevention
- Always pass wsConstructor explicitly in Node entry points (import WebSocket from 'ws')
- Pin a Node version policy and document the WebSocket requirement
- For binary frames, bring a custom connector since the built-in one is text-only
When it happens
Trigger: Calling the client factory with only { url, protocols } in Node.js (globalThis.WebSocket undefined on Node < 22, or behind a flag on early 22 builds), or in a bundled/pruned environment where the global was stripped.
Common situations: Using a browser-oriented WS client during SSR or in a bot/script; CI running an older Node image; test environment (jsdom) without a WebSocket polyfill; custom runtimes lacking the WHATWG WebSocket.
Related errors
- Channel gateway stream error:
- [chat-sync] pullMessages failed for
- [chat-ws] dropped malformed newMessages payload:
- [chat-ws] socket error:
- [chat-ws] ws error event:
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/4fa8987cd44f213c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/better-ws/src/client/index.ts:872
waiters.add(wait.emit)
void wait.promise.finally(() => {
waiters.delete(wait.emit)
}).catch(() => {})
return wait.promise
}
}
return client
}
function createSocketConnector(options: ClientUrlOptions): ClientConnector<string> {
return {
connect(events) {
const WsConstructor = options.wsConstructor ?? globalThis.WebSocket
if (!WsConstructor) {
throw new Error('No WebSocket constructor is available. Pass `wsConstructor` or use a connector.')
}
const ws = new WsConstructor(options.url, options.protocols)
return new Promise<ClientConnection<string>>((resolve, reject) => {
let opened = false
let failedBeforeOpen = false
ws.onopen = () => {
opened = true
resolve({
send: message => ws.send(message),
close: (code, reason) => ws.close(code, reason),
})
}
ws.onmessage = (event) => {
if (typeof event.data === 'string') {
events.message(event.data)
return
}View on GitHub (pinned to 677329427f)