{"record":{"id":"6b68ddd67d0e0386","repo":"agalwood/Motrix","slug":"websocket-is-not-connected","errorCode":null,"errorMessage":"WebSocket is not connected","messagePattern":"WebSocket is not connected","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/core/engine/aria2/web-socket-transport.ts","lineNumber":62,"sourceCode":"      })\n    })\n  }\n\n  disconnect(): void {\n    if (!this.ws) return\n    this.connected = false\n    this.ws.removeAllListeners()\n    this.ws.close()\n    this.ws = null\n  }\n\n  isConnected(): boolean {\n    return this.connected\n  }\n\n  send(data: string): void {\n    if (!this.ws || !this.connected) {\n      throw new Error('WebSocket is not connected')\n    }\n    this.ws.send(data)\n  }\n\n  onMessage(handler: MessageHandler): void {\n    this.messageHandler = handler\n  }\n\n  onClose(handler: CloseHandler): void {\n    this.closeHandler = handler\n  }\n\n  onError(handler: ErrorHandler): void {\n    this.errorHandler = handler\n  }\n}\n","sourceCodeStart":44,"sourceCodeEnd":79,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/engine/aria2/web-socket-transport.ts#L44-L79","documentation":"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.","triggerScenarios":"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`.","commonSituations":"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.","solutions":["Always await transport.connect(url) before calling send()","Register an onClose handler and pause/requeue outgoing sends until reconnect completes","Check transport.isConnected() before calling send() and reconnect if false","Implement a reconnect-with-backoff wrapper that re-establishes the connection on close before retrying sends"],"exampleFix":"// before\ntransport.send(JSON.stringify(request)) // may throw if not connected\n// after\nif (!transport.isConnected()) { await transport.connect(url) }\ntransport.send(JSON.stringify(request))","handlingStrategy":"validation","validationCode":"function assertConnected(transport: WebSocketTransport): void {\n  if (!transport.isConnected()) {\n    throw new Error('Cannot send: WebSocket is not connected. Call connect() first.')\n  }\n}\n// Or simply check before send:\nif (!transport.isConnected()) {\n  await transport.connect(url)\n}","typeGuard":null,"tryCatchPattern":"try {\n  transport.send(data)\n} catch (e) {\n  if (e instanceof Error && e.message === 'WebSocket is not connected') {\n    await transport.connect(url)\n    transport.send(data) // retry after reconnect\n  } else throw e\n}","preventionTips":["Always await connect() before any send() call","Register an onClose handler to track disconnections and reconnect before retrying sends","Check isConnected() as a guard before send in RPC client wrappers","Implement a connection state machine that queues or rejects sends when disconnected"],"tags":["websocket","aria2","transport","connection","rpc"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}