redis/node-redis · error · Error

emitInvalidate is only supported with RESP3

Error message

emitInvalidate is only supported with RESP3

What it means

emitInvalidate surfaces RESP3 push/invalidate events to user code via the 'invalidate' emitter. It therefore requires RESP3; with any other RESP version it is rejected in #validateOptions.

Solutions

  1. Set RESP: 3 and connect to a redis >= 6 server.
  2. Or remove emitInvalidate and consume invalidations through the clientSideCache mechanism instead.

Example fix

// before
createClient({ emitInvalidate: true });

// after
createClient({ emitInvalidate: true, RESP: 3 });
Defensive patterns

Strategy: validation

Validate before calling

function validateInvalidateOptions(options) {
  const resp = options?.RESP ?? 3;
  if (options?.emitInvalidate && resp !== 3) {
    throw new Error('emitInvalidate requires RESP: 3');
  }
  return options;
}

Prevention

When it happens

Trigger: createClient({ emitInvalidate: true, RESP: 2 }) or omitting RESP while the negotiated version falls below 3.

Common situations: Wanting raw invalidation events on a RESP2 connection; legacy config; older redis server that cannot do RESP3.

Related errors


AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11). Data as JSON: /api/errors/b69805db7209d571. Report an issue: GitHub.

Appendix: source

Thrown at packages/client/lib/client/index.ts:797

        if (push[1] !== null) {
          for (const key of push[1]) {
            this.emit('invalidate', key);
          }
        } else {
          this.emit('invalidate', null);
        }
        return true
      });
    }
  }

  #validateOptions(options?: RedisClientOptions<M, F, S, RESP, TYPE_MAPPING>) {
    const resp = options?.RESP ?? DEFAULT_RESP;
    if (options?.clientSideCache && resp !== 3) {
      throw new Error('Client Side Caching is only supported with RESP3');
    }
    if (options?.emitInvalidate && resp !== 3) {
      throw new Error('emitInvalidate is only supported with RESP3');
    }
    if (options?.clientSideCache && options?.emitInvalidate) {
      throw new Error('emitInvalidate is not supported (or necessary) when clientSideCache is enabled');
    }
    if (options?.maintNotifications && options?.maintNotifications !== 'disabled' && resp !== 3) {
      throw new Error('Graceful Maintenance is only supported with RESP3');
    }
  }

  #initiateOptions(options: RedisClientOptions<M, F, S, RESP, TYPE_MAPPING> = {}): RedisClientOptions<M, F, S, RESP, TYPE_MAPPING> {

    // Convert username/password to credentialsProvider if no credentialsProvider is already in place
    if (!options.credentialsProvider && (options.username || options.password)) {

      options.credentialsProvider = {
        type: 'async-credentials-provider',
        credentials: async () => ({
          username: options.username,

View on GitHub (pinned to 90fd0652bc)