Skip to content

Ignore undefined options so that they don't override defaults #93

Open

Description

@mriedem

We're using the library in a function like this:

  const retryWithExponentialBackoff = async (operation, { retries, minTimeout, maxTimeout, context } = {}) => {
    const op = retry.operation({
      retries: retries !== undefined ? retries : config.natsJetStream.retries,
      minTimeout,
      maxTimeout
    })

    return new Promise((resolve, reject) => {
      op.attempt(async currentAttempt => {
        try {
          const result = await operation()
          resolve(result)
        } catch (err) {
          log.warn({ attempt: currentAttempt, err, context }, 'Operation failed, retrying')
          if (!op.retry(err)) {
            reject(op.mainError())
          }
        }
      })
    })
  }

Where retries defaults to 60 but minTimeout and maxTimeout are undefined by default.

Because of this code:

node-retry/lib/retry.js

Lines 17 to 26 in 11efd6e

var opts = {
retries: 10,
factor: 2,
minTimeout: 1 * 1000,
maxTimeout: Infinity,
randomize: false
};
for (var key in options) {
opts[key] = options[key];
}

We're always wiping out the defaults for minTimeout and maxTimeout and basically never sleep between retry attempts.

Recreate:

> options = { retries: 3, minTimeout: undefined, maxTimeout:undefined }
{ retries: 3, minTimeout: undefined, maxTimeout: undefined }
> const retry2 = require('retry')
undefined
> ro = retry2.operation(options)
RetryOperation {
  _originalTimeouts: [ null, null, null ],
  _timeouts: [ NaN, NaN, NaN ],
  _options: { forever: false, unref: undefined, maxRetryTime: undefined },
  _maxRetryTime: Infinity,
  _fn: null,
  _errors: [],
  _attempts: 1,
  _operationTimeout: null,
  _operationTimeoutCb: null,
  _timeout: null,
  _operationStart: null,
  _timer: null
}
> options.minTimeout = 1000
1000
> ro2 = retry2.operation(options)
RetryOperation {
  _originalTimeouts: [ null, null, null ],
  _timeouts: [ NaN, NaN, NaN ],
  _options: { forever: false, unref: undefined, maxRetryTime: undefined },
  _maxRetryTime: Infinity,
  _fn: null,
  _errors: [],
  _attempts: 1,
  _operationTimeout: null,
  _operationTimeoutCb: null,
  _timeout: null,
  _operationStart: null,
  _timer: null
}
> options
{ retries: 3, minTimeout: 1000, maxTimeout: undefined }
> options.maxTimeout = 5000
5000
> options
{ retries: 3, minTimeout: 1000, maxTimeout: 5000 }
> 
> 
> retry2.operation(options)
RetryOperation {
  _originalTimeouts: [ 1000, 2000, 4000 ],
  _timeouts: [ 1000, 2000, 4000 ],
  _options: { forever: false, unref: undefined, maxRetryTime: undefined },
  _maxRetryTime: Infinity,
  _fn: null,
  _errors: [],
  _attempts: 1,
  _operationTimeout: null,
  _operationTimeoutCb: null,
  _timeout: null,
  _operationStart: null,
  _timer: null
}

Activity

  1. changed the title [-]Ignore undefined options[/-] [+]Ignore undefined options so that they don't override defaults[/+] on Mar 16, 2026
  2. bybraveHQ commented on Jul 5, 2026

    @bybraveHQ

    Fixed in the maintained fork @bybrave/retry2: undefined option values are now ignored instead of overriding defaults, so retry.timeouts({ retries: undefined }) keeps the default of 10 rather than producing 0. npm i @bybrave/retry2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions