{"id":"c6f46ec38a10eaab","repo":"redis/node-redis","slug":"the-client-is-closed","errorCode":null,"errorMessage":"The client is closed","messagePattern":"The client is closed","errorType":"exception","errorClass":"ClientClosedError","httpStatus":null,"severity":"error","filePath":"packages/client/lib/client/index.ts","lineNumber":1924,"sourceCode":"    );\n  }\n\n  /**\n   * @internal\n   */\n  async _executeMulti(\n    commands: Array<RedisMultiQueuedCommand>,\n    selectedDB?: number\n  ) {\n    assertNoHimportSessionCommands(commands);\n\n    const dirtyWatch = this._self.#dirtyWatch;\n    this._self.#dirtyWatch = undefined;\n    const watchEpoch = this._self.#watchEpoch;\n    this._self.#watchEpoch = undefined;\n\n    if (!this._self.#socket.isOpen) {\n      throw new ClientClosedError();\n    }\n\n    if (dirtyWatch) {\n      throw new WatchError(dirtyWatch);\n    }\n\n    if (watchEpoch && watchEpoch !== this._self.socketEpoch) {\n      throw new WatchError('Client reconnected after WATCH');\n    }\n\n    const batchSize = commands.length;\n\n    return trace(CHANNELS.TRACE_BATCH,\n      async () => {\n        const typeMapping = this._commandOptions?.typeMapping;\n        const chainId = Symbol('MULTI Chain');\n        const promises: Array<Promise<unknown>> = [\n          this._self.#queue.addCommand(['MULTI'], { chainId }),","sourceCodeStart":1906,"sourceCodeEnd":1942,"githubUrl":"https://github.com/redis/node-redis/blob/bb5beb56578573910e2ee8f39681edc214c41398/packages/client/lib/client/index.ts#L1906-L1942","documentation":"ClientClosedError (message 'The client is closed') is thrown/rejected from the command-execution funnels — sendCommand (index.ts:1626), _executePipeline (1861), _executeMulti (1924) — and from the socket connect path (socket.ts) when the socket is not open. It signals that the client has been closed (or never connected) and will not accept commands. The same error class is used across all entry points so callers can branch on `err instanceof ClientClosedError` uniformly.","triggerScenarios":"Calling `client.get('k')` after `await client.close()`; calling any command before `client.connect()`; using a client whose connection dropped and was closed; calling `.exec()` on a multi/pipeline after the client was closed; the socket's reconnect gave up and the client moved to a closed state.","commonSituations":"Forgetting to `await client.connect()`; using the client after `client.close()` (e.g. in a shutdown handler or after an error); a previous fatal error that closed the client but the caller keeps issuing commands; reusing a client across request handlers without ensuring it is open.","solutions":["Call `await client.connect()` before issuing commands, and guard command code with `if (client.isOpen)`.","After `client.close()`, do not reuse the instance — create a new client (or call connect() again if appropriate).","Handle ClientClosedError in your command path and reconnect/recreate the client.","In long-running services, connect once at startup and close only at shutdown."],"exampleFix":"// before\nconst client = createClient({ url });\nawait client.get('k'); // throws ClientClosedError\n\n// after\nconst client = createClient({ url });\nawait client.connect();\nawait client.get('k');","handlingStrategy":"try-catch","validationCode":"async function safeGet(client, key) {\n  if (!client.isOpen) {\n    await client.connect();\n  }\n  return client.get(key);\n}","typeGuard":"function isClientClosedError(err: unknown): boolean {\n  return err instanceof Error && err.message === 'The client is closed';\n}","tryCatchPattern":"try {\n  return await client.get(key);\n} catch (err) {\n  if (err instanceof Error && err.message === 'The client is closed') {\n    await client.connect();\n    return client.get(key);\n  }\n  throw err;\n}","preventionTips":["Always `await client.connect()` before issuing commands.","Guard command code with `if (client.isOpen)`.","Do not reuse a client after close(); create a new one.","Connect once at process startup; close only at shutdown."],"tags":["lifecycle","connection","client-closed"],"analyzedSha":"bb5beb56578573910e2ee8f39681edc214c41398","analyzedAt":"2026-08-03T19:09:15.686Z","schemaVersion":2}