redis/node-redis · error · Error
expirationRefreshRatio must be less than or equal to 1
Error message
expirationRefreshRatio must be less than or equal to 1
What it means
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.
Source
Thrown at packages/client/lib/authx/token-manager.ts:146
* TokenManager is responsible for obtaining/refreshing tokens and notifying listeners about token changes.
* It uses an IdentityProvider to request tokens. The token refresh is scheduled based on the token's TTL and
* the expirationRefreshRatio configuration.
*
* The TokenManager should be disposed when it is no longer needed by calling the dispose method on the Disposable
* returned by start.
*/
export class TokenManager<T> {
private currentToken: Token<T> | null = null;
private refreshTimeout: NodeJS.Timeout | null = null;
private listener: TokenStreamListener<T> | null = null;
private retryAttempt: number = 0;
constructor(
private readonly identityProvider: IdentityProvider<T>,
private readonly config: TokenManagerConfig
) {
if (this.config.expirationRefreshRatio > 1) {
throw new Error('expirationRefreshRatio must be less than or equal to 1');
}
if (this.config.expirationRefreshRatio < 0) {
throw new Error('expirationRefreshRatio must be greater or equal to 0');
}
}
/**
* Starts the token manager and returns a Disposable that can be used to stop the token manager.
*
* @param listener The listener that will receive token updates.
* @param initialDelayMs The initial delay in milliseconds before the first token refresh.
*/
public start(listener: TokenStreamListener<T>, initialDelayMs: number = 0): Disposable {
if (this.listener) {
this.stop();
}
this.listener = listener;View on GitHub (pinned to bb5beb5657)
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].
Example fix
// before
new TokenManager(provider, { expirationRefreshRatio: 75 });
// after
new TokenManager(provider, { expirationRefreshRatio: 0.75 }); Defensive patterns
Strategy: validation
Validate before calling
function makeTokenManager(provider, cfg) {
if (!(cfg.expirationRefreshRatio >= 0 && cfg.expirationRefreshRatio <= 1)) {
throw new RangeError('expirationRefreshRatio must be within [0, 1]');
}
return new TokenManager(provider, cfg);
} Type guard
function isValidRefreshRatio(v: unknown): v is number {
return typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 1;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- expirationRefreshRatio must be greater or equal to 0
- TokenManager is not running, but refresh was called
- TokenManager is not running, but a new token was received
- TokenManager is not running but received an error: ${errorMe
- tls socket option is set to ${options.socket.tls} which is m
AI-assisted analysis of redis/node-redis@bb5beb5657 (2026-08-03).
Data as JSON: /data/errors/95e8345b27b44230.json.
Report an issue: GitHub.