redis/node-redis · error · TypeError

topologyRefreshOnReconnectionAttempt must be undefined, fals

Error message

topologyRefreshOnReconnectionAttempt must be undefined, false, a non-negative integer, or a function

What it means

Thrown from ClusterReconnectionTracker.#validate (cluster-reconnection-tracker.ts:45), reached via the constructor, which RedisClusterSlots calls at cluster construction. The topologyRefreshOnReconnectionAttemptStrategy option must be undefined, false, a non-negative integer, or a function; anything else (string, negative/float number, true, object) is rejected up front with a TypeError.

Source

Thrown at packages/client/lib/cluster/cluster-reconnection-tracker.ts:45

  /**
   * Validates that a strategy value is acceptable before use.
   * @throws If the strategy is not supported
   */
  #validate(strategy?: ClusterTopologyRefreshOnReconnectionAttemptStrategy) {
    if (
      strategy === undefined ||
      strategy === false ||
      typeof strategy === 'function' ||
      (
        typeof strategy === 'number' &&
        Number.isInteger(strategy) &&
        strategy >= 0
      )
    ) {
      return;
    }

    throw new TypeError('topologyRefreshOnReconnectionAttempt must be undefined, false, a non-negative integer, or a function');
  }

  constructor(strategy?: ClusterTopologyRefreshOnReconnectionAttemptStrategy) {
    this.#validate(strategy);
    this.#strategy = strategy;
  }

  get reconnectingAddresses() {
    return new Set(this.#reconnectingClients.values());
  }

  get firstReconnectionAt() {
    return this.#firstReconnectionAt;
  }

  /**
   * Records a reconnection attempt for the given client and evaluates whether
   * the configured delay has elapsed since the first attempt in this cycle.

View on GitHub (pinned to bb5beb5657)

Solutions

  1. Pass one of: undefined (default 5s), false or 0 (disable), a non-negative integer (ms delay), or a function.
  2. When loading from env, coerce with Number() and validate Number.isInteger(n) && n >= 0 before passing.
  3. If a float was intended, round it: Math.round(value).

Example fix

// before
const cluster = createCluster({
  rootNodes: [{ socket: { host: 'h', port: 7000 } }],
  topologyRefreshOnReconnectionAttemptStrategy: '5000' // string -> TypeError
});

// after
const delay = Number(process.env.TOPO_REFRESH_DELAY);
const cluster = createCluster({
  rootNodes: [{ socket: { host: 'h', port: 7000 } }],
  topologyRefreshOnReconnectionAttemptStrategy: Number.isInteger(delay) && delay >= 0 ? delay : undefined
});
Defensive patterns

Strategy: validation

Validate before calling

function normalizeStrategy(v: unknown) {
  if (v === undefined || v === false || typeof v === 'function') return v;
  if (typeof v === 'number' && Number.isInteger(v) && v >= 0) return v;
  throw new TypeError('invalid topologyRefreshOnReconnectionAttemptStrategy');
}
const cluster = createCluster({ rootNodes, topologyRefreshOnReconnectionAttemptStrategy: normalizeStrategy(raw) });

Type guard

function isStrategy(v: unknown): v is undefined | false | number | ((t: number) => false | undefined | number) {
  return v === undefined || v === false || typeof v === 'function' || (typeof v === 'number' && Number.isInteger(v) && v >= 0);
}

Prevention

When it happens

Trigger: Constructing createCluster({ topologyRefreshOnReconnectionAttemptStrategy: <invalid> }) — e.g. passing '5000' (string), -1, 1.5, true, or {}.

Common situations: Loading config from env/JSON where numbers arrive as strings; passing a float delay; misreading the docs and passing true to 'enable'.

Related errors


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