Skip to content

fix: clamp negative Retry-After delays - #878

Open
sylvesterkaczmarek wants to merge 2 commits into
openai:mainfrom
sylvesterkaczmarek:fix/clamp-negative-retry-after
Open

fix: clamp negative Retry-After delays#878
sylvesterkaczmarek wants to merge 2 commits into
openai:mainfrom
sylvesterkaczmarek:fix/clamp-negative-retry-after

Conversation

@sylvesterkaczmarek

Copy link
Copy Markdown

Summary

Treat negative or already-elapsed Retry-After delays as zero before passing them to the retry sleeper.

Fixes #853.

Problem

RetryingHttpClient parses three server-directed retry-delay forms:

  • Retry-After-Ms numeric milliseconds;
  • Retry-After numeric seconds;
  • Retry-After HTTP dates.

The parsed value is currently converted directly to Duration and passed to Sleeper.

That means values such as:

Retry-After: -1
Retry-After-Ms: -1
Retry-After: Wed, 21 Oct 2015 07:28:00 GMT

can produce a negative duration. With the default sleeper, that can make a retryable response fail while trying to sleep instead of retrying immediately.

Past HTTP dates are especially normal under clock skew or network transit: once the requested instant has passed, the remaining delay is simply zero.

Fix

Clamp the parsed nanosecond delay at the shared retry-delay boundary:

Duration.ofNanos(retryAfterNanos.toLong().coerceAtLeast(0L))

This is applied after all supported Retry-After parsing, so both synchronous and asynchronous retry paths receive the same non-negative duration.

Invalid/unparseable headers continue to fall back to the existing exponential backoff behavior.

Regression coverage

Added focused sync/async coverage for:

  • negative numeric Retry-After seconds;
  • negative Retry-After-Ms milliseconds;
  • an RFC 1123 HTTP date five seconds in the past.

All three cases require exactly Duration.ZERO and a successful retry.

Validation

  • branch is based directly on current upstream main at 6a46d024ed67e2be889a4c729837a664d5e7902c;
  • branch is 0 commits behind upstream;
  • production diff is 4 additions / 2 deletions in RetryingHttpClient.kt;
  • no retry-count, retryability, jitter, maximum-backoff, or response-close behavior changes.

Full repository validation is left to GitHub Actions because this environment does not have a complete local checkout/toolchain for the repository.

Risk

Low. Positive server-directed delays are unchanged. Only negative parsed delays are normalized to zero, which is equivalent to the requested retry time already having elapsed.

@sylvesterkaczmarek
sylvesterkaczmarek requested a review from a team as a code owner August 18, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: clamp negative Retry-After delays before sleeping

1 participant