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
- Ensure the strategy function returns false, undefined, 0, or a non-negative integer only.
- Round/clamp the computed delay: return Math.max(0, Math.round(delay)).
- Add a unit test for the strategy function covering edge inputs (0, negative, NaN).
- 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
- Round and clamp strategy return values: Math.max(0, Math.round(x)).
- Guard against NaN/Infinity in Date.now() arithmetic.
- Unit-test the strategy function across edge inputs.
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
- topologyRefreshOnReconnectionAttempt must be undefined…
- Reconnect strategy should return `false | Error | number`…
- Cannot split : key region does not align with keystep
- Cannot split : key region overruns the arguments
- Client Side Caching is only supported with RESP3
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)