{"id":"9a3da0410a3d87c9","repo":"redis/node-redis","slug":"topologyrefreshonreconnectionattempt-must-be-undef","errorCode":null,"errorMessage":"topologyRefreshOnReconnectionAttempt must be undefined, false, a non-negative integer, or a function","messagePattern":"topologyRefreshOnReconnectionAttempt must be undefined, false, a non-negative integer, or a function","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/client/lib/cluster/cluster-reconnection-tracker.ts","lineNumber":45,"sourceCode":"  /**\n   * Validates that a strategy value is acceptable before use.\n   * @throws If the strategy is not supported\n   */\n  #validate(strategy?: ClusterTopologyRefreshOnReconnectionAttemptStrategy) {\n    if (\n      strategy === undefined ||\n      strategy === false ||\n      typeof strategy === 'function' ||\n      (\n        typeof strategy === 'number' &&\n        Number.isInteger(strategy) &&\n        strategy >= 0\n      )\n    ) {\n      return;\n    }\n\n    throw new TypeError('topologyRefreshOnReconnectionAttempt must be undefined, false, a non-negative integer, or a function');\n  }\n\n  constructor(strategy?: ClusterTopologyRefreshOnReconnectionAttemptStrategy) {\n    this.#validate(strategy);\n    this.#strategy = strategy;\n  }\n\n  get reconnectingAddresses() {\n    return new Set(this.#reconnectingClients.values());\n  }\n\n  get firstReconnectionAt() {\n    return this.#firstReconnectionAt;\n  }\n\n  /**\n   * Records a reconnection attempt for the given client and evaluates whether\n   * the configured delay has elapsed since the first attempt in this cycle.","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/redis/node-redis/blob/bb5beb56578573910e2ee8f39681edc214c41398/packages/client/lib/cluster/cluster-reconnection-tracker.ts#L27-L63","documentation":"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.","triggerScenarios":"Constructing createCluster({ topologyRefreshOnReconnectionAttemptStrategy: <invalid> }) — e.g. passing '5000' (string), -1, 1.5, true, or {}.","commonSituations":"Loading config from env/JSON where numbers arrive as strings; passing a float delay; misreading the docs and passing true to 'enable'.","solutions":["Pass one of: undefined (default 5s), false or 0 (disable), a non-negative integer (ms delay), or a function.","When loading from env, coerce with Number() and validate Number.isInteger(n) && n >= 0 before passing.","If a float was intended, round it: Math.round(value)."],"exampleFix":"// before\nconst cluster = createCluster({\n  rootNodes: [{ socket: { host: 'h', port: 7000 } }],\n  topologyRefreshOnReconnectionAttemptStrategy: '5000' // string -> TypeError\n});\n\n// after\nconst delay = Number(process.env.TOPO_REFRESH_DELAY);\nconst cluster = createCluster({\n  rootNodes: [{ socket: { host: 'h', port: 7000 } }],\n  topologyRefreshOnReconnectionAttemptStrategy: Number.isInteger(delay) && delay >= 0 ? delay : undefined\n});","handlingStrategy":"validation","validationCode":"function normalizeStrategy(v: unknown) {\n  if (v === undefined || v === false || typeof v === 'function') return v;\n  if (typeof v === 'number' && Number.isInteger(v) && v >= 0) return v;\n  throw new TypeError('invalid topologyRefreshOnReconnectionAttemptStrategy');\n}\nconst cluster = createCluster({ rootNodes, topologyRefreshOnReconnectionAttemptStrategy: normalizeStrategy(raw) });","typeGuard":"function isStrategy(v: unknown): v is undefined | false | number | ((t: number) => false | undefined | number) {\n  return v === undefined || v === false || typeof v === 'function' || (typeof v === 'number' && Number.isInteger(v) && v >= 0);\n}","tryCatchPattern":null,"preventionTips":["Validate config-derived values before passing them in.","Coerce env strings with Number() and check Number.isInteger && >= 0.","Pass undefined to accept the documented 5s default."],"tags":["cluster","configuration","validation","reconnect"],"analyzedSha":"bb5beb56578573910e2ee8f39681edc214c41398","analyzedAt":"2026-08-03T19:09:15.686Z","schemaVersion":2}