redis/node-redis · error · TypeError

topologyRefreshOnReconnectionAttempt should return `false |…

Error message

topologyRefreshOnReconnectionAttempt should return `false | undefined | number`, got ${delay} instead

What it means

Thrown inside ClusterReconnectionTracker.#getDelay when a user-supplied topologyRefreshOnReconnectionAttemptStrategy function returns a value that is not false, undefined, 0, or a non-negative integer. Unlike the constructor-time validation, this fires at runtime during a live reconnection cycle when the function is actually called.

Solutions

  1. Ensure the strategy function returns false, undefined, 0, or a non-negative integer only.
  2. Round/clamp the computed delay: return Math.max(0, Math.round(delay)).
  3. Add a unit test for the strategy function covering edge inputs (0, negative, NaN).
  4. If you do not need custom logic, use a plain integer or undefined instead of a function.

Example fix

// before
topologyRefreshOnReconnectionAttemptStrategy: (firstAt) => (Date.now() - firstAt) / 2 // float -> TypeError

// after
topologyRefreshOnReconnectionAttemptStrategy: (firstAt) => Math.max(0, Math.round((Date.now() - firstAt) / 2))
Defensive patterns

Strategy: validation

Validate before calling

function safeStrategy(firstReconnectionAt: number): false | undefined | number {
  const delay = Math.max(0, Math.round(computeDelay(firstReconnectionAt)));
  return Number.isFinite(delay) ? delay : false;
}

Type guard

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

Prevention

When it happens

Trigger: Providing topologyRefreshOnReconnectionAttemptStrategy as a function that returns a negative number, a float, a string, null, or a Promise. Triggered when a cluster node starts reconnecting and the tracker evaluates the delay.

Common situations: A custom strategy function with an off-by-one or Math.round omission returning 5.5; returning a string delay; returning null instead of undefined/false; logic bug that returns NaN when Date.now() math goes wrong.

Related errors


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

Appendix: source

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

   */
  #getDelay(firstReconnectionAt: number) {
    if (this.#strategy === undefined) {
      return ClusterReconnectionTracker.#DEFAULT_TOPOLOGY_REFRESH_ON_RECONNECTION_ATTEMPT;
    }

    if (this.#strategy === false) {
      return;
    }

    if (typeof this.#strategy === 'number') {
      return this.#strategy;
    }

    const delay = this.#strategy(firstReconnectionAt);
    if (delay === false || delay === undefined || delay === 0) return;

    if (!Number.isInteger(delay) || delay < 0) {
      throw new TypeError(`topologyRefreshOnReconnectionAttempt should return \`false | undefined | number\`, got ${delay} instead`);
    }

    return delay;
  }

  #clearTimestampIfClean() {
    if (this.#reconnectingClients.size === 0) {
      this.#firstReconnectionAt = undefined;
    }
  }
}

View on GitHub (pinned to 90fd0652bc)