Skip to content

LoggingHttpMessageHandler changes HttpHeaders added with TryAddWithoutValidation when Trace logging is enabled #132009

Description

@asamokhvalov-agicins

Description

LoggingHttpMessageHandler changes the observable behavior of HttpRequestMessage when a known header is added using HttpHeaders.TryAddWithoutValidation().

When LogLevel.Trace is enabled for Microsoft.Extensions.Http, the logging pipeline enumerates HttpHeaders, which causes lazily stored raw header values to become materialized as typed headers.

As a result, the request sent over the wire differs from the original request.

This does not happen when:

  • using new HttpClient();
  • or calling RemoveAllLoggers() on IHttpClientBuilder;
  • or disabling Trace logging.

Reproduction Steps

Mimimal reproduction:

var services = new ServiceCollection();

services.AddLogging(builder =>
{
    builder.SetMinimumLevel(LogLevel.Trace);
});

services.AddHttpClient("test");

var provider = services.BuildServiceProvider();

var factory = provider.GetRequiredService<IHttpClientFactory>();

var client = factory.CreateClient("test");

var request = new HttpRequestMessage(HttpMethod.Get, "https://example.com");

request.Headers.TryAddWithoutValidation(
    "Accept",
    "application/vnd.example+json;version=1");

await client.SendAsync(request);

If logging is removed:

services.AddHttpClient("test")
    .RemoveAllLoggers();

the original raw header value is preserved.

Expected behavior

Logging should be non-invasive.
Enumerating headers for logging purposes should not modify the behavior or serialization of the outgoing request.

Actual behavior

The request is modified before being sent.

For example we added the following header into httpRequest:
Accept: application/vnd.mycompany.json;version=2.1.4

is sent as:
Accept: application/vnd.mycompany.json; version=2.1.4
after Trace logging enumerates the headers.

Regression?

No response

Known Workarounds

No response

Configuration

  • .NET 10
  • Microsoft.Extensions.Http

Other information

I did little investigation.

The issue appears to originate from
Microsoft.Extensions.Http.Logging.HttpHeadersLogValue

specifically:

foreach (KeyValuePair<string, IEnumerable<string>> kvp in Headers)
{
    values.Add(new KeyValuePair<string, object>(kvp.Key, kvp.Value));
}

Enumerating Headers forces lazy parsing/materialization of known headers.
After this happens, the request is serialized differently.

Activity

  1. dotnet-policy-service commented on Aug 7, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @karelz, @dotnet/ncl
    See info in area-owners.md if you want to be subscribed.

  2. added and removed
    untriagedNew issue has not been triaged by the area owner
    on Aug 7, 2026
  3. added this to the 11.0.0 milestone on Aug 7, 2026
  4. MihaZupan commented on Aug 7, 2026

    @MihaZupan
    Member

    Thanks for the report. We should be enumerating via the NonValidated API if our goal is to log the values. We don't need them to be parsed (waste of perf + possible subtle differences as noted here)

  5. locked and limited conversation to collaborators on Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions