{"record":{"id":"e653e1fa01f529b0","repo":"redis/node-redis","slug":"reconnect-strategy-should-return-false-error","errorCode":null,"errorMessage":"Reconnect strategy should return `false | Error | number`, got ${retryIn} instead","messagePattern":"Reconnect strategy should return `false \\| Error \\| number`, got (.+?) instead","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/client/lib/client/socket.ts","lineNumber":125,"sourceCode":"    this.#connectTimeout = options?.connectTimeout ?? 5000;\n    this.#reconnectStrategy = this.#createReconnectStrategy(options);\n    this.#socketFactory = this.#createSocketFactory(options);\n    this.#socketTimeout = options?.socketTimeout;\n    this.#clientId = clientId;\n  }\n\n  #createReconnectStrategy(options?: RedisSocketOptions): ReconnectStrategyFunction {\n    const strategy = options?.reconnectStrategy;\n    if (strategy === false || typeof strategy === 'number') {\n      return () => strategy;\n    }\n\n    if (strategy) {\n      return (retries, cause) => {\n        try {\nconst retryIn = strategy(retries, cause);\n          if (retryIn !== false && !(retryIn instanceof Error) && typeof retryIn !== 'number') {\n            throw new TypeError(`Reconnect strategy should return \\`false | Error | number\\`, got ${retryIn} instead`);\n          }\n          return retryIn;\n        } catch (err) {\n          publish(CHANNELS.ERROR, () => ({\n            error: err as Error,\n            origin: 'client',\n            internal: false,\n            clientId: this.#clientId\n          }));\n          this.emit('error', err);\n          return this.defaultReconnectStrategy(retries, err);\n        }\n      };\n    }\n\n    return this.defaultReconnectStrategy;\n  }\n","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/client/lib/client/socket.ts#L107-L143","documentation":"Thrown inside the wrapped reconnectStrategy when the user-supplied function returns a value that is not false, an Error, or a number. The library validates the return type on every reconnect decision because an invalid delay would break the backoff loop. The thrown TypeError is caught internally, emitted as an 'error' event, and the default strategy is used as a fallback.","triggerScenarios":"Passing socket: { reconnectStrategy(retries, cause) { return '500'; } } (string), or returning null, undefined, a Promise, or NaN from the custom strategy function. Any non-(false|Error|number) return triggers it.","commonSituations":"Typo in a custom strategy returning a string like '500' instead of 500; returning retryIn > someMax as a boolean expression that evaluates to undefined; migrating from an older client whose strategy contract differed; returning a Promise instead of a plain value.","solutions":["Make the custom reconnectStrategy return a number (ms delay), false (stop reconnecting), or an Error (stop with error) — nothing else.","If using a string from config, coerce with Number() and validate before returning.","Ensure the function is synchronous; do not return a Promise.","Listen for the 'error' event to confirm whether the fallback default strategy took over."],"exampleFix":"// before\nreconnectStrategy(retries) {\n  return retries < 10 ? '500' : false; // string -> TypeError\n}\n\n// after\nreconnectStrategy(retries) {\n  return retries < 10 ? 500 : false; // number | false\n}","handlingStrategy":"validation","validationCode":"function validStrategy(retries: number, cause: Error): false | Error | number {\n  const delay = Math.min(retries * 50, 2000);\n  return delay;\n}\n// test: assert typeof validStrategy(0,new Error()) === 'number' || v === false || v instanceof Error","typeGuard":"function isValidReconnectReturn(v: unknown): v is false | Error | number {\n  return v === false || v instanceof Error || typeof v === 'number';\n}","tryCatchPattern":null,"preventionTips":["Always return a number, false, or an Error from reconnectStrategy — never a string or undefined.","Keep the strategy synchronous; do not return a Promise.","Unit-test the strategy function over edge inputs."],"tags":["reconnect","configuration","validation","typescript"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}