agalwood/Motrix · error · Error

WebSocket is not connected

Error message

WebSocket is not connected

What it means

Thrown as a plain Error by WebSocketTransport.send when called before a connection is established (this.ws is null) or after the connection was closed/disconnected (this.connected is false). This is a synchronous guard — send() does not queue messages. The transport must be connected via connect() (which resolves on the 'open' event) before any send call.

Source

Thrown at src/core/engine/aria2/web-socket-transport.ts:62

      })
    })
  }

  disconnect(): void {
    if (!this.ws) return
    this.connected = false
    this.ws.removeAllListeners()
    this.ws.close()
    this.ws = null
  }

  isConnected(): boolean {
    return this.connected
  }

  send(data: string): void {
    if (!this.ws || !this.connected) {
      throw new Error('WebSocket is not connected')
    }
    this.ws.send(data)
  }

  onMessage(handler: MessageHandler): void {
    this.messageHandler = handler
  }

  onClose(handler: CloseHandler): void {
    this.closeHandler = handler
  }

  onError(handler: ErrorHandler): void {
    this.errorHandler = handler
  }
}

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Always await transport.connect(url) before calling send()
  2. Register an onClose handler and pause/requeue outgoing sends until reconnect completes
  3. Check transport.isConnected() before calling send() and reconnect if false
  4. Implement a reconnect-with-backoff wrapper that re-establishes the connection on close before retrying sends

Example fix

// before
transport.send(JSON.stringify(request)) // may throw if not connected
// after
if (!transport.isConnected()) { await transport.connect(url) }
transport.send(JSON.stringify(request))
Defensive patterns

Strategy: validation

Validate before calling

function assertConnected(transport: WebSocketTransport): void {
  if (!transport.isConnected()) {
    throw new Error('Cannot send: WebSocket is not connected. Call connect() first.')
  }
}
// Or simply check before send:
if (!transport.isConnected()) {
  await transport.connect(url)
}

Try / catch

try {
  transport.send(data)
} catch (e) {
  if (e instanceof Error && e.message === 'WebSocket is not connected') {
    await transport.connect(url)
    transport.send(data) // retry after reconnect
  } else throw e
}

Prevention

When it happens

Trigger: transport.send(data) is called before connect() resolves, after disconnect() is called, or after the 'close' event fired (which sets this.connected = false). The check is `!this.ws || !this.connected`.

Common situations: RPC client sends a request before awaiting connect(); the WebSocket dropped mid-session and the caller didn't reconnect before the next send; a race condition where disconnect() runs concurrently with an in-flight send; the aria2 RPC server restarted and the connection closed but the caller wasn't notified.

Related errors


AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12). Data as JSON: /api/errors/6b68ddd67d0e0386. Report an issue: GitHub.