Repository navigation
feat(http): add option to retry only unprocessed mutations - #2251
Merged
Vincent Biret (baywet) merged 2 commits intoNov 13, 2026
Merged
Vincent Biret (baywet) merged 2 commits into
Vincent Biret (baywet) merged 2 commits into
Conversation
Add RetryHandlerOption.retryUnprocessedMutationsOnly, set through a new constructor. It defaults to false, which keeps the current behavior. When it is true, POST and PATCH requests are retried only after a 429 or 503 response, which indicate the server did not process the request. A 504 is returned to the caller, because the server may already have applied the request and a retry could apply it twice. Other methods are unaffected.
Jackson Smith (jackson-asmith)
requested a review
from a team
as a code owner
November 13, 2026 17:13
There was a problem hiding this comment.
🟡 Changes recommended
The tests still omit the POST-to-GET redirect regression, leaving retries unverified for a 302 → 504 → 200 sequence that should record POST, GET, GET.
1 open issue
What changed in this PR
Adds opt-in retry protection to Kiota’s OkHttp middleware to reduce duplicate POST/PATCH side effects after gateway timeouts, while preserving existing defaults.
Changes:
- Adds
retryUnprocessedMutationsOnly, defaulting tofalse, with documentation of its safety assumptions. - When enabled, restricts POST/PATCH retries to 429 and 503 on every attempt; other methods remain unchanged.
- Adds tests for defaults, method/status combinations, successive responses, and per-request configuration.
| File | Description |
|---|---|
| components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RetryHandlerTest.java | Adds regression coverage for the opt-in retry policy. |
| components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RetryHandler.java | Applies method-aware eligibility to each retry. |
| components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RetryHandlerOption.java | Exposes and documents the option while preserving constructor defaults. |
Review effort: Balanced
Run RedirectHandler and RetryHandler together with the option on. A POST that a 302 turns into a GET is retried after a 504, and a POST kept by a 307 is not.
This was referenced Nov 13, 2026
Vincent Biret (baywet)
approved these changes
Nov 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #2250
This ports microsoft/kiota-dotnet#864 to Java. The other ports so far are microsoft/kiota-http-go#312 and microsoft/kiota-python#897.
Problem
RetryHandler retries 429, 503 and 504 responses whatever the HTTP method. For POST and PATCH, a retry after a 504 can apply the request twice. A 504 means a gateway stopped waiting, not that the server did nothing, so the first attempt may already have succeeded. With Microsoft Graph's sendMail, this sends the same email twice.
IShouldRetry already receives the request, so a caller can filter by method today. Most callers, including users of the generated SDKs, never set IShouldRetry, though, so they keep the retries that can send twice. A built-in option makes the safe behavior a single setting.
Change
This adds RetryHandlerOption.retryUnprocessedMutationsOnly(), matching the .NET option.
RetryHandlerOption has no setters, so the setting comes through a new constructor. The existing constructors pass false.
KiotaClientFactory adds RedirectHandler before RetryHandler, so the retry handler only sees the request for the current redirect hop and resends exactly that. Checking request.method() is therefore always the method being resent.
Tests
RetryHandlerTest has 18 new tests, using MockWebServer like the existing ones, covering:
With the new check removed from the retry condition, the 5 tests for the new behavior fail and the rest pass. Locally with JDK 21, ./gradlew :components:http:okHttp:build passes, including Spotless and SpotBugs. I didn't run the Java 8 build or the Android API-level lint locally.