{"id":"95e8345b27b44230","repo":"redis/node-redis","slug":"expirationrefreshratio-must-be-less-than-or-equal","errorCode":null,"errorMessage":"expirationRefreshRatio must be less than or equal to 1","messagePattern":"expirationRefreshRatio must be less than or equal to 1","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/client/lib/authx/token-manager.ts","lineNumber":146,"sourceCode":" * TokenManager is responsible for obtaining/refreshing tokens and notifying listeners about token changes.\n * It uses an IdentityProvider to request tokens. The token refresh is scheduled based on the token's TTL and\n * the expirationRefreshRatio configuration.\n *\n * The TokenManager should be disposed when it is no longer needed by calling the dispose method on the Disposable\n * returned by start.\n */\nexport class TokenManager<T> {\n  private currentToken: Token<T> | null = null;\n  private refreshTimeout: NodeJS.Timeout | null = null;\n  private listener: TokenStreamListener<T> | null = null;\n  private retryAttempt: number = 0;\n\n  constructor(\n    private readonly identityProvider: IdentityProvider<T>,\n    private readonly config: TokenManagerConfig\n  ) {\n    if (this.config.expirationRefreshRatio > 1) {\n      throw new Error('expirationRefreshRatio must be less than or equal to 1');\n    }\n    if (this.config.expirationRefreshRatio < 0) {\n      throw new Error('expirationRefreshRatio must be greater or equal to 0');\n    }\n  }\n\n  /**\n   * Starts the token manager and returns a Disposable that can be used to stop the token manager.\n   *\n   * @param listener The listener that will receive token updates.\n   * @param initialDelayMs The initial delay in milliseconds before the first token refresh.\n   */\n  public start(listener: TokenStreamListener<T>, initialDelayMs: number = 0): Disposable {\n    if (this.listener) {\n      this.stop();\n    }\n\n    this.listener = listener;","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/redis/node-redis/blob/bb5beb56578573910e2ee8f39681edc214c41398/packages/client/lib/authx/token-manager.ts#L128-L164","documentation":"The TokenManager constructor validates that `expirationRefreshRatio` (the fraction of a token's lifetime after which a refresh is scheduled) is within [0,1]. A value > 1 is meaningless and dangerous — it would schedule a refresh after the token has already expired, leaving a window with no valid token — so the constructor throws synchronously before the manager is usable.","triggerScenarios":"Constructing `new TokenManager(provider, { expirationRefreshRatio: 1.5 })` or any value strictly greater than 1; computing the ratio from config/env where the math inverts (e.g. dividing by a small number) and yields >1; passing a percentage (e.g. 75) instead of a ratio (0.75).","commonSituations":"Config mistake: treating the field as a percentage (75) rather than a ratio (0.75); copy-paste from a doc example with a typo; dynamic config where an operator enters '120' expecting percent; refactoring that flips numerator/denominator.","solutions":["Set expirationRefreshRatio to a value in [0,1], typically 0.5–0.8 (refresh when 50–80% of lifetime has elapsed).","If your value is a percentage, divide by 100 before passing: `expirationRefreshRatio: pct / 100`.","Add a unit test / config schema asserting the ratio is within [0,1]."],"exampleFix":"// before\nnew TokenManager(provider, { expirationRefreshRatio: 75 });\n\n// after\nnew TokenManager(provider, { expirationRefreshRatio: 0.75 });","handlingStrategy":"validation","validationCode":"function makeTokenManager(provider, cfg) {\n  if (!(cfg.expirationRefreshRatio >= 0 && cfg.expirationRefreshRatio <= 1)) {\n    throw new RangeError('expirationRefreshRatio must be within [0, 1]');\n  }\n  return new TokenManager(provider, cfg);\n}","typeGuard":"function isValidRefreshRatio(v: unknown): v is number {\n  return typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 1;\n}","tryCatchPattern":null,"preventionTips":["Treat expirationRefreshRatio as a ratio (0.7), never a percentage (70).","Validate the value at config load and in unit tests.","Document the [0,1] bound wherever the config is exposed."],"tags":["config","validation","authx","token-manager"],"analyzedSha":"bb5beb56578573910e2ee8f39681edc214c41398","analyzedAt":"2026-08-03T19:09:15.686Z","schemaVersion":2}