Skip to content

withRetry throws undefined when maxAttempts is 0 or negative — no precondition guard #95

@ooloth

Description

@ooloth

Why

If maxAttempts is passed as 0 or a negative number, withRetry's loop body never executes and the function falls through to throw lastError! where lastError was never assigned — throwing undefined as a non-null-asserted never-type, producing an unintelligible failure.

Current state

io/utils/retry.ts line 59: for (let attempt = 1; attempt <= opts.maxAttempts; attempt++). When maxAttempts is 0, the loop body never runs. Line 78: throw lastError! — TypeScript's non-null assertion silences the type error, but lastError is undefined at runtime, so the throw propagates undefined rather than a real error.

Ideal state

  • withRetry validates opts.maxAttempts >= 1 at entry with a clear error (e.g. invariant(opts.maxAttempts >= 1, 'maxAttempts must be at least 1')).
  • Calling withRetry with maxAttempts: 0 produces an immediate, descriptive error rather than a confusing undefined throw.

Starting points

  • io/utils/retry.ts — lines 59 and 78, the loop guard and the final throw

QA plan

  1. Call withRetry(fn, { maxAttempts: 0 }) — expect an immediate error naming the invalid maxAttempts, not a throw of undefined.
  2. Call withRetry(fn, { maxAttempts: 3 }) — expect normal retry behaviour unchanged.

Done when

withRetry throws a descriptive error at entry when maxAttempts is less than 1, rather than eventually throwing undefined.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions