apiRequest's 429 handling ignores Retry-After in HTTP-date form, and its `|| "Rate limited..."` fallback message is dead code

Open
#572 8 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@foxxx009 is already working on this.

Since Sep 28, 2026.

  • #573 by @foxxx009 — open
  • #579 by @PINYOPATTANAWASANPORN — open
  • #586 by @Proxima84-code — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
25/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript
Domain
api

Research direction

The 429 branch is in apiRequest() in src/lib/api.ts, where the Retry-After header is parsed with parseInt and the || fallback is dead. Two open pull requests (#573 and #586) already target this, so read them and the thread before starting. Done means HTTP-date and delay-seconds values both populate the wait message and ApiRequestError.retryAfter, the fallback message is reachable, and unit tests cover the four header cases.

Written by the indexing model from the issue text.

Description

bug enhancement good first issue

Problem

src/lib/api.ts → apiRequest(), from the rate-limit handling added in #44:

if (res.status === 429) {
  const retryAfter = res.headers.get("Retry-After");
  const seconds = retryAfter ? parseInt(retryAfter, 10) : NaN;
  const waitMsg = Number.isFinite(seconds)
    ? ` Please wait ${seconds} second${seconds === 1 ? "" : "s"} before trying again.`
    : "";
  throw new ApiRequestError(
    `You're doing that too fast.${waitMsg}` || `Rate limited. Please try again later.`,
    429,
    Number.isFinite(seconds) ? seconds : undefined,
  );
}
  1. HTTP-date Retry-After is dropped. RFC 9110 §10.2.3 allows Retry-After to be either delay-seconds or an HTTP-date, such as Retry-After: Wed, 21 Oct 2026 07:28:00 GMT, which proxies and CDNs commonly send. parseInt("Wed, 21 Oct…", 10) is NaN, so the wait time disappears from both the message and ApiRequestError.retryAfter. Callers that read retryAfter to throttle retries get undefined.
  2. The fallback message is unreachable. The left side of || is a template literal that always starts with "You're doing that too fast.", so it's always truthy. "Rate limited. Please try again later." can never be used, which suggests the intended "no wait info" message was lost.

Suggested fix

  • Parse both forms. Use the seconds if /^\d+$/ matches. Otherwise use Date.parse(value) and compute Math.max(0, Math.ceil((date - Date.now()) / 1000)).
  • Choose the message explicitly: the "wait N seconds" wording when seconds are known, and the plain fallback otherwise. Remove the dead ||.
  • Add unit tests for delay-seconds, an HTTP-date, a missing header and a garbage header value. lib/api.ts has limited coverage (#370).

Related: #44, #370.

Dominant language
TypeScript
Stars
1
Forks
94
Avg merge
1h 2m
Merged PRs (30d)
25

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from MergeFi/frontend

All issues in MergeFi/frontend

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.