{"id":"f75c3381fd4193b8","repo":"redis/node-redis","slug":"socket-already-opened","errorCode":null,"errorMessage":"Socket already opened","messagePattern":"Socket already opened","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/client/lib/client/socket.ts","lineNumber":237,"sourceCode":"      return cause;\n    } else if (retryIn instanceof Error) {\n      this.#isOpen = false;\n      publish(CHANNELS.ERROR, () => ({\n        error: cause,\n        origin: 'client',\n        internal: false,\n        clientId: this.#clientId\n      }));\n      this.emit('error', cause);\n      return new ReconnectStrategyError(retryIn, cause);\n    }\n\n    return retryIn;\n  }\n\n  async connect(): Promise<void> {\n    if (this.#isOpen) {\n      throw new Error('Socket already opened');\n    }\n\n    this.#isOpen = true;\n    return this.#connect();\n  }\n\n  async #connect(): Promise<void> {\n    let retries = 0;\n    do {\n      try {\n        const connectStartTime = performance.now();\n        const socket = this.#socket = await this.#createSocket();\n        this.emit('connect');\n\n        try {\n          await this.#initiateWhileSocketAlive(socket);\n\n          // Check if socket was closed/destroyed during initiator execution","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/redis/node-redis/blob/bb5beb56578573910e2ee8f39681edc214c41398/packages/client/lib/client/socket.ts#L219-L255","documentation":"Thrown from RedisSocket.connect() (socket.ts:237) when #isOpen is already true. The socket guard prevents a second connect attempt over a live connection. It is a plain Error, thrown synchronously to the caller of client.connect().","triggerScenarios":"Calling client.connect() twice; awaiting connect() in a retry loop that already succeeded; connecting a client that the application auto-connected elsewhere.","commonSituations":"Double await on the same connect() promise race; reconnect logic that calls connect() without checking isOpen; framework lifecycle hooks firing twice.","solutions":["Guard the call: check client.isOpen before calling connect(), or memoize the connect promise.","Use createClient().connect() once at startup and reuse the instance.","If reconnecting after close(), call close()/destroy() first, then connect()."],"exampleFix":"// before\nawait client.connect();\nawait client.connect(); // throws 'Socket already opened'\n\n// after\nif (!client.isOpen) await client.connect();","handlingStrategy":"validation","validationCode":"if (client.isOpen) { /* already connected, skip */ } else { await client.connect(); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Memoize the connect() promise so multiple callers share one attempt.","Check client.isOpen before connect().","Connect once at process startup and reuse the client."],"tags":["lifecycle","connection","socket"],"analyzedSha":"bb5beb56578573910e2ee8f39681edc214c41398","analyzedAt":"2026-08-03T19:09:15.686Z","schemaVersion":2}