redis/node-redis · error · TypeError

topologyRefreshOnReconnectionAttempt must be undefined…

Error message

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

What it means

Thrown by ClusterReconnectionTracker constructor validation when the topologyRefreshOnReconnectionAttemptStrategy option is not one of: undefined, false, a non-negative integer, or a function. The strategy controls when a cluster topology refresh is triggered after a node starts reconnecting; an invalid type is rejected at client construction time.

Solutions

  1. Pass undefined (default 5s), false or 0 (disabled), a non-negative integer (ms delay), or a function.
  2. If reading from env/config, coerce with Number() and validate Number.isInteger(v) && v >= 0 before passing.
  3. Pass a function (firstReconnectionAt) => delay for custom logic instead of a value.
  4. Do not pass true; use undefined for the default-enabled behavior.

Example fix

// before
const cluster = createCluster({ rootNodes, topologyRefreshOnReconnectionAttemptStrategy: '5000' });
// TypeError at construction

// after
const cluster = createCluster({ rootNodes, topologyRefreshOnReconnectionAttemptStrategy: 5000 });
Defensive patterns

Strategy: validation

Validate before calling

function validateTopologyStrategy(v: unknown): void {
  if (v === undefined || v === false || typeof v === 'function' ||
      (typeof v === 'number' && Number.isInteger(v) && v >= 0)) return;
  throw new TypeError('Invalid topologyRefreshOnReconnectionAttemptStrategy');
}
validateTopologyStrategy(configValue);

Type guard

function isTopologyStrategy(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: Passing cluster option topologyRefreshOnReconnectionAttemptStrategy as a string ('5000'), a negative number (-1), a float (5.5), or an object. Passing it as a boolean true (only false is accepted).

Common situations: Reading the delay from an environment variable as a string and passing it uncoerced; passing a float milliseconds value; copy-paste from docs that showed a function but leaving stray characters; passing true expecting it to mean 'enabled'.

Related errors


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

Appendix: 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 90fd0652bc)