redis/node-redis · error · ClientClosedError

The client is closed

Error message

The client is closed

What it means

Thrown from RedisSocket.quit() (socket.ts:446) when the socket is not open. quit() is meant to gracefully close an active connection (it sends QUIT and waits for the reply), so calling it on an already-closed/never-opened client is a programming error. Throws ClientClosedError synchronously.

Source

Thrown at packages/client/lib/client/socket.ts:446

        if (this.#socket.writableNeedDrain) break;
      }
    } catch (err) {
      // net.Socket.write can throw synchronously on a half-closed socket
      // (writeAfterFIN -> EPIPE) before the 'close' event fires. The pending
      // command has already been moved to #waitingForReply by the queue's
      // generator, so the close handler will reject it on reconnect.
      if (!err || (err as NodeJS.ErrnoException).code !== 'EPIPE') {
        throw err;
      }
    } finally {
      this.#socket.uncork();
    }
  }

  async quit<T>(fn: () => Promise<T>): Promise<T> {
    if (!this.#isOpen) {
      throw new ClientClosedError();
    }

    this.#isOpen = false;
    const reply = await fn();
    this.destroySocket();
    return reply;
  }

  close() {
    if (!this.#isOpen) {
      throw new ClientClosedError();
    }

    this.#isOpen = false;
  }

  destroy() {
    if (!this.#isOpen) {

View on GitHub (pinned to bb5beb5657)

Solutions

  1. Check client.isOpen before calling quit().
  2. Use destroy() for forced shutdown that tolerates an already-closed state, or guard with try/catch.
  3. Drive shutdown from a single place to avoid racing quit()/close() calls.

Example fix

// before
await client.quit(); // throws 'The client is closed' if already closed

// after
if (client.isOpen) await client.quit();
Defensive patterns

Strategy: validation

Validate before calling

if (client.isOpen) { await client.quit(); }

Try / catch

try { await client.quit(); } catch (e) { if (!/client is closed/i.test(e.message)) throw e; }

Prevention

When it happens

Trigger: Calling client.quit() after client.close()/destroy(), or on a client whose connection never established, or after an unexpected close already ran.

Common situations: Shutdown handlers calling quit() unconditionally; double shutdown in finally blocks; calling quit() after a fatal 'error' event already closed the socket.

Related errors


AI-assisted analysis of redis/node-redis@bb5beb5657 (2026-08-03). Data as JSON: /data/errors/0a3aab2cbaed2dbd.json. Report an issue: GitHub.