Skip to content

Fix "The request message was already sent" error when following redirects - #60

Draft
jefim with Claude wants to merge 1 commit into
mainfrom
claude/investigate-http-request-exception
Draft

Fix "The request message was already sent" error when following redirects#60
jefim with Claude wants to merge 1 commit into
mainfrom
claude/investigate-http-request-exception

Conversation

@Claude

@Claude Claude AI commented Aug 20, 2026

Copy link
Copy Markdown

Summary

A customer on HTTP/1.1 with FollowRedirects=true reported intermittent exceptions: "The request message was already sent. Cannot send the same request message multiple times." (~24/1500 requests over 8 hours).

Root cause

GetHttpRequestResponseAsync built a single HttpRequestMessage (bound to a single HttpContent) and dispatched it once. A System.Net.Http.HttpRequestMessage can only be sent one time — once sent it sets an internal flag and any re-dispatch throws this exact InvalidOperationException. When the handler follows a 3xx redirect, or when the shared cached HttpClient (default CacheHttpClient=true) internally re-dispatches under concurrency/connection churn, the same message is re-sent and the guard trips. This explains the low, environment-dependent error rate: only requests that hit a redirect or a re-dispatched connection are affected.

Fix

  • Construct a fresh HttpRequestMessage and HttpContent per send attempt via a content factory (Func<HttpContent>), so an internal re-send never reuses a consumed message.
  • Transparently retry (bounded to 3 attempts) only on the specific "already sent" InvalidOperationException.
  • Content is now owned per attempt; removed the outer httpContent disposal in finally accordingly.
  • Split the send logic into BuildRequestMessage and SendRequestMessageAsync helpers; behavior otherwise unchanged.

Testing

  • Added RequestShouldFollowRedirectForRequestWithBody which POSTs a JSON body through a 307 redirect with FollowRedirects=true and asserts the body reaches the final endpoint.
  • dotnet test Frends.HTTP.Request.sln: 23 passed, 0 failed, 2 skipped.

Test plan

  • Build succeeds (0 errors)
  • Full Request test suite passes
  • New redirect-with-body test passes

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.

2 participants