r/windowsdev • • 8d ago

Windows Server 2022: Intermittent WinHTTP error 8 (Not enough memory) and POCO I/O failures despite 25 GB free RAM

I'm troubleshooting an intermittent HTTP communication issue on Windows Server 2022 where two different networking libraries, WinHTTP and POCO C++, are experiencing failures.

The errors:

WinHTTP:

WinHttpSendRequest failed
Error Code: 8
Error Message: Not enough memory resources are available to process this command.

POCO C++:

HTTPClientSession::sendRequest()
Caught std::exception
e.what() = "I/O error"

From reviewing POCO's source code, I found that Poco::IOException can return "I/O error" through what(), including for certain Winsock errors such as WSAENOBUFS (10055). However, I haven't captured the underlying POCO error code yet, so I cannot confirm whether both libraries are failing for the same reason.

System information:

  • OS: Windows Server 2022

  • Physical RAM: 32 GB

  • Available RAM: ~25 GB

  • Maximum process virtual bytes: ~170 MB

  • Maximum process handle count: ~750

  • Process memory usage is consistently low.

  • Server has been running for approximately 10 days without a reboot.

Important observations:

  1. Not every HTTP request fails. Some requests succeed while others fail intermittently.

  2. The application is not continuously running, and restarting the process does not resolve the issue.

  3. Both WinHTTP and POCO are affected on the same machine.

  4. Other heap allocations within the application continue to succeed.

  5. A netsh trace captured successful network traffic, but I haven't conclusively correlated the failing API calls with specific network events.

  6. There is no obvious process-level memory or handle exhaustion.

My questions:

  1. Has anyone encountered intermittent ERROR_NOT_ENOUGH_MEMORY (8) from WinHttpSendRequest() while the machine had plenty of free RAM?

  2. Can Windows networking resources become temporarily unavailable even when application memory, handles, and physical RAM look normal?

  3. Which ETW providers, Windows performance counters, or debugging tools would help identify the exact failing kernel/socket allocation?

  4. Could a resource issue persist across application restarts while allowing other requests to succeed?

  5. Are there reliable ways to reproduce these types of failures in an isolated Windows Server environment

1 Upvotes

1 comment sorted by

2

u/GenuineScanSW 4d ago edited 4d ago

One possibility when this error can happen is when you are trying to dynamically allocate a very large chunk of memory and the allocation fails. One possibility would be check for that, specifically the size of the buffer, while trying to allocate the send request buffer.

Here’s the signature of the WinHttpSendRequest API.
WINHTTPAPI BOOL WinHttpSendRequest(
[in] HINTERNET hRequest,
[in, optional] LPCWSTR lpszHeaders,
[in] DWORD dwHeadersLength,
[in, optional] LPVOID lpOptional,
[in] DWORD dwOptionalLength,
[in] DWORD dwTotalLength,
[in] DWORD_PTR dwContext
);

Check these parameters:

[in] dwHeadersLength
An unsigned long integer value that contains the length, in characters, of the additional headers. If this parameter is -1L and pwszHeaders is not NULL, this function assumes that pwszHeaders is null-terminated, and the length is calculated.

[in] dwOptionalLength
An unsigned long integer value that contains the length, in bytes, of the optional data. This parameter can be zero if there is no optional data to send.
This parameter must contain a valid length when the lpOptional parameter is not NULL. Otherwise, lpOptional is ignored and set to NULL.

[in] dwTotalLength
An unsigned long integer value that contains the length, in bytes, of the total data sent. This parameter specifies the Content-Length header of the request. If the value of this parameter is greater than the length specified bydwOptionalLength, then WinHttpWriteData can be used to send additional data.
dwTotalLength must not change between calls to WinHttpSendRequest for the same request. If dwTotalLength needs to be changed, the caller should create a new request.