Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Transient NullReferenceException when calling HttpClient.GetAsync #115179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wesleychan-ms opened this issue Apr 30, 2025 · 4 comments
Closed

Transient NullReferenceException when calling HttpClient.GetAsync #115179

wesleychan-ms opened this issue Apr 30, 2025 · 4 comments

Comments

@wesleychan-ms
Copy link

wesleychan-ms commented Apr 30, 2025

My team has been using HttpClient.GetAsync on .NET 462 without issues, but upon migrating to .NET 8, we have been getting transient null references within the GetAsync call as shown in the stack trace below. The flow that calls HttpClient.GetAsync is fairly high volume and we see that maybe 1% of our calls have the NullReferenceException whereas the other 99% are successful.

Furthermore, upon being requeued, the previously failed calls are successful, indicating that it is not an issue with specific edge cases. I was wondering if this is a known issue, as other code paths we have that use HttpClient see these NullReferenceExceptions.

Our code is fairly simple and just attaches the Auth header and then makes the GetAsync call like below:

HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
HttpResponseMessage response = await httpClient.GetAsync(url).ConfigureAwait(false);

The stack trace in the exception is:

System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Net.Http.HttpConnection.WriteHeaderCollection(HttpHeaders headers, String cookiesFromContainer)
   at System.Net.Http.HttpConnection.WriteHeaders(HttpRequestMessage request, HttpMethod normalizedMethod)
   at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Apr 30, 2025
@MihaZupan
Copy link
Member

MihaZupan commented Apr 30, 2025

My first guess would be that the header collection got corrupted due to concurrent use.
Do you have any custom handlers/logic that might be modifying the reading/writing headers concurrently to the request being sent? Or modifying the DefaultRequestHeaders collection after the client initialization?

Since it sounds like this is (relatively) common, would you be able to capture a memory dump at the time you hit the exception? E.g. FailFast from the first chance exception handler.
That should be enough to let us confirm whether that's the issue / where something else is going wrong.

@wfurt wfurt added the needs-author-action An issue or pull request that requires more info or actions from the author. label Apr 30, 2025
@wesleychan-ms
Copy link
Author

@MihaZupan thanks for the reply! I just took a look through our code and I think you are correct that we initialize the HttpClient in the constructor of our StatelessService object in Program.cs. Then we have multiple lower-level threads that are adjusting the HttpClient Auth Header at the same time.

So, the recommended fix here would be to initiate the HttpClients in the RunAsync method instead, so that it happens at thread initialization?

@dotnet-policy-service dotnet-policy-service bot removed the needs-author-action An issue or pull request that requires more info or actions from the author. label May 1, 2025
@stephentoub
Copy link
Member

stephentoub commented May 1, 2025

So, the recommended fix here would be to initiate the HttpClients in the RunAsync method instead, so that it happens at thread initialization?

The recommendation would be to not have this as a default header and instead have each call site create an HttpRequestMessage with whatever headers that request needs, isolated from every other request. The shared HttpClient should be treated as being immutable.

You could create a new HttpClient at each use, but you'd want to ensure that you were sharing the same underlying HttpMessageHandler and not doing new HttpClient(), which would result in a new connection pool being created per use and is very expensive.

@wesleychan-ms
Copy link
Author

Got it and makes sense. Will look to define the auth headers in the request instead. Thank you very much!

@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label May 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants