redis/node-redis · error · TypeError

tls socket option is set to ${options.socket.tls} which is m

Error message

tls socket option is set to ${options.socket.tls} which is mismatch with protocol or the URL ${options.url} passed

What it means

During parseOptions, when both `options.url` and `options.socket` are provided, the client checks that any explicit `socket.tls` agrees with the URL's scheme (rediss:// => tls true, redis:// => tls false). A mismatch means the developer asked for two contradictory things (e.g. a rediss:// URL but socket.tls=false, or redis:// with socket.tls=true), which would produce a confusing TLS handshake failure later — so it fails fast with a TypeError showing both values.

Source

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

    };
  }

  static create<
    M extends RedisModules = {},
    F extends RedisFunctions = {},
    S extends RedisScripts = {},
    RESP extends RespVersions = 3,
    TYPE_MAPPING extends TypeMapping = {}
  >(this: void, options?: RedisClientOptions<M, F, S, RESP, TYPE_MAPPING>) {
    return RedisClient.factory(options)(options);
  }

  static parseOptions<O extends AnyRedisClientOptions>(options: O): O {
    if (options?.url) {
      const parsed = RedisClient.parseURL(options.url);
      if (options.socket) {
        if (options.socket.tls !== undefined && options.socket.tls !== parsed.socket.tls) {
          throw new TypeError(`tls socket option is set to ${options.socket.tls} which is mismatch with protocol or the URL ${options.url} passed`)
        }
        parsed.socket = Object.assign(options.socket, parsed.socket);
      }

      Object.assign(options, parsed);
    }
    return options;
  }

  static parseURL(url: string): AnyRedisClientOptions & {
    socket: Exclude<AnyRedisClientOptions['socket'], undefined> & {
      tls: boolean
    }
  } {
    // unix:// URIs use a non-special scheme; WHATWG URL refuses to parse an
    // authority (e.g. `user:pass@`) without a host, so handle it separately.
    if (url.startsWith('unix:')) {
      return RedisClient.#parseUnixURL(url);

View on GitHub (pinned to bb5beb5657)

Solutions

  1. Make TLS consistent: use rediss:// together with socket.tls omitted (it is derived from the URL), or set socket.tls to match the scheme.
  2. Prefer specifying TLS via the URL scheme only and drop the explicit socket.tls to avoid the conflict.
  3. Centralize connection config so the URL scheme and socket.tls cannot drift apart.

Example fix

// before
createClient({ url: 'rediss://host:6379', socket: { tls: false } });

// after
createClient({ url: 'rediss://host:6379' });
Defensive patterns

Strategy: validation

Validate before calling

function resolveRedisOptions(raw) {
  if (raw.url && raw.socket?.tls !== undefined) {
    const schemeTls = raw.url.startsWith('rediss://');
    if (raw.socket.tls !== schemeTls) {
      throw new TypeError('socket.tls conflicts with the URL scheme');
    }
  }
  return raw;
}

Prevention

When it happens

Trigger: `createClient({ url: 'rediss://host:6379', socket: { tls: false } })`; `createClient({ url: 'redis://host:6379', socket: { tls: true } })`; merging a tls:false default socket config with a rediss:// URL from env.

Common situations: Layered config (base config sets socket.tls, env provides the URL) where the two disagree; copy-paste from an example that hard-coded socket.tls; migrating from redis:// to rediss:// without removing an explicit socket.tls override.

Related errors


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