Transient TcpGlobalPortReservation STATUS_INVALID_PARAMETER on Windows 11 without port exhaustion

Hi,

I am investigating recurring Windows 11 TCP/IP System events 4231/4266 and have managed to capture the issue at ETW level several times.

So far I have 7 natural occurrences captured in detail. The failures were triggered by different requesters/processes, including Chrome, ChatGPT, Discord and svchost/NetworkService, and I have observed both TCP and UDP cases.

This does not look like classic ephemeral-port exhaustion.

Visible port occupancy, TIME_WAIT and ephemeral-port usage were low during the captures. User-mode reproduction attempts with thousands of wildcard/Port0 binds, including SO_RANDOMIZE_PORT-oriented tests, did not reproduce the failure.

The recurring low-level pattern is:

socket creation succeeds
-> socket options succeed
-> wildcard / Port0 bind begins
-> Microsoft-Windows-TCPIP / TcpGlobalPortReservation
ReservationType = 16
StartPort = 0
NumberOfPorts = 1
Protocol = UDP 17 or TCP 6
Status = 0xC000000D (STATUS_INVALID_PARAMETER)
-> bind failure propagates as 0xC0000209 (STATUS_TOO_MANY_ADDRESSES)
-> shortly afterwards automatic port allocation succeeds again

The latest capture was:

Windows 11 Pro
Build 26200
Event 4266
RecordId 402098
Requester: Chrome NetworkService
PID 19304
UDP / IPv6 wildcard Port0

Relevant ETW timeline:

T+0.068 ms
Microsoft-Windows-Winsock-Sockets
SockCreate Start
PID 19304

T+0.090 ms
Microsoft-Windows-Winsock-AFD
AfdCreate Enter
UDP / IPv6 socket
Status 0

T+0.132 ms
Winsock SockSetOpt
Status 0

T+0.139 ms
Winsock SockSetOpt
Status 0

T+0.145 ms
Microsoft-Windows-Winsock-AFD
AfdBindWithAddress Enter
Address ::
Status 0

T+0.160 ms
Microsoft-Windows-TCPIP
TcpGlobalPortReservation
ReservationType = 16
IPTransportProtocol = 17
StartPort = 0
NumberOfPorts = 1
Status = 0xC000000D

T+0.167 ms
Microsoft-Windows-TCPIP
UdpBindEndpointPortFailure
Status = 0xC0000209

T+0.169 ms
Microsoft-Windows-Winsock-AFD
AfdBind Exit
Status = 0xC0000209

T+0.173 ms
Winsock failure returned to the caller

T+0.196 ms
failed socket closed

T+0.346 ms
new socket creation begins

T+0.409 ms
new AfdBindWithAddress(::slight_smile: begins

T+0.452 ms
AfdBindWithAddress succeeds with [::]:60546

So there are only about 15 microseconds between the successful AFD bind entry and the first TCPIP failure, and roughly 0.3 ms later automatic allocation succeeds again.

I also captured a broad WPR/ETW trace containing:

  • Winsock-AFD
  • Winsock-Sockets
  • TCPIP
  • WFP
  • NDIS
  • Hyper-V VmSwitch
  • VFP
  • HNS
  • WinNAT

The saved trace reported 0 lost buffers and 0 lost events.

I could not identify a corresponding failure immediately before the TCPIP event in HNS, VFP, WinNAT, WFP, NDIS or VmSwitch.

There was normal WSL/Hyper-V network activity shortly before the failure, but it completed successfully and did not share the failing Chrome socket/endpoint/resource.

The first visible actual failure therefore remains TcpGlobalPortReservation returning STATUS_INVALID_PARAMETER.

Environment, for context only (none of these are proven as the cause):

Windows 11 Pro build 26200
Hyper-V enabled
Virtual Machine Platform enabled
WSL
HNS / vmcompute / WinNAT
VirtualBox
Kaspersky
Kaspersky VPN
Tailscale
Realtek Gaming 2.5GbE

My main questions are:

  1. Does anyone know what internal validation condition can cause TcpGlobalPortReservation with ReservationType=16, StartPort=0 and NumberOfPorts=1 to transiently return STATUS_INVALID_PARAMETER?

  2. Has anyone seen this exact pattern before without actual ephemeral-port exhaustion?

  3. Is there a useful WinDbg / kernel-debugging approach to catch the internal state at the moment this happens?

  4. Would a stack trace on the AFD/TCPIP events realistically provide more useful information, or would public symbols only show the call route without the internal state that caused STATUS_INVALID_PARAMETER?

  5. Are there any known interactions with Hyper-V/WSL or third-party network filter drivers that could cause this kind of transient port-reservation failure?

I have the full ETW/WPR trace, the exact failure branch, event XML, metadata and raw socket/AFD/TCPIP event data available.

I am not claiming this is necessarily a Windows bug. I am mainly trying to determine whether this can be debugged further from outside Microsoft, and what the most useful next diagnostic step would be.

Thanks.

not an answer

this is some maybe answer with some random google , a bit of itchy fingers.

and windows 10

the start port = 0 does not seem to be a valid start port if i test it with netsh

netsh interface ipv6 add excludedportrange

from netsh help ? commands

Example:

  add excludedportrange protocol=tcp startport=50000 numberofports=20

test results

netsh interface ipv6>add excludedportrange protocol=tcp startport=0 numberofports=1
The parameter is incorrect.

netsh interface ipv6>add excludedportrange protocol=tcp startport=0 numberofports=2
The parameter is incorrect.

netsh interface ipv6>add excludedportrange protocol=tcp startport=0 numberofports=20
The parameter is incorrect.

netsh interface ipv6>add excludedportrange protocol=tcp startport=20 numberofports=20
Ok.

netsh interface ipv6>delete excludedportrange protocol=tcp startport=20 numberofports=20
Ok.

netsh interface ipv6>add excludedportrange protocol=tcp startport=0 numberofports=20
The parameter is incorrect.

netsh interface ipv6>add excludedportrange protocol=tcp startport=1 numberofports=20
Ok.

netsh interface ipv6>delete excludedportrange protocol=tcp startport=1 numberofports=20
Ok.

a sample stack where this is processes

the HRESULT 0xc000000d seems to be returned from from an IOCTL call delivered by nsi!nsiioctl

NSI!NsiIoctl+0x1af:
00007fff`017021bf 25000000c0 and eax,0C0000000h
0:000> k

Child-SP RetAddr Call Site

00 000000ab`9ecf7250 00007fff`01701d95 NSI!NsiIoctl+0x1af
01 000000ab`9ecf72f0 00007ffe`faff382f NSI!NsiSetAllParametersEx+0x35
02 000000ab`9ecf7330 00007ffe`faff37db WINNSI!NsiRpcSetAllParametersEx+0x3f
03 000000ab`9ecf7440 00007ffe`a2bddbb8 WINNSI!NsiRpcSetAllParameters+0x6b
04 000000ab`9ecf74c0 00007ffe`a2bddc11 NETIOHLP!NhIpExcludedPortRangeHelper+0x23c
05 000000ab`9ecf75c0 00007ff6`5ce25ac9 NETIOHLP!NhIpHandleAddExcludedPortRange+0x11
06 000000ab`9ecf7610 00007ff6`5ce24939 NETSH!ExecuteHandler+0xd5
07 000000ab`9ecf7680 00007ff6`5ce24a4a NETSH!GenericMonitor+0x2a9
08 000000ab`9ecf7730 00007ff6`5ce24a4a NETSH!GenericMonitor+0x3ba
09 000000ab`9ecf77e0 00007ff6`5ce25566 NETSH!GenericMonitor+0x3ba
0a 000000ab`9ecf7890 00007ff6`5ce26957 NETSH!ProcessHelperCommand2+0x12e
0b 000000ab`9ecf7900 00007ff6`5ce270df NETSH!ProcessCommand+0x727
0c 000000ab`9ecf79a0 00007ff6`5ce27c7f NETSH!MainCommandLoop+0x1d3
0d 000000ab`9ecf7a10 00007ff6`5ce2addd NETSH!MainFunction+0x7af
0e 000000ab`9ecffef0 00007fff`006e7374 NETSH!__wmainCRTStartup+0x14d
0f 000000ab`9ecfff30 00007fff`01a7cc91 KERNEL32!BaseThreadInitThunk+0x14
10 000000ab`9ecfff60 00000000`00000000 ntdll!RtlUserThreadStart+0x21
0:000> r
rax=00000000c000000d rbx=00000000c000000d rcx=00007fff01acd784
rdx=0000000000000000 rsi=00000000000004e4 rdi=000000ab9ecf7338
rip=00007fff017021bf rsp=000000ab9ecf7250 rbp=0000000000000048
r8=000000ab9ecf7218 r9=0000000000000048 r10=0000000000000000
r11=0000000000000246 r12=000000ab9ecf7460 r13=0000000000120013
r14=000000ab9ecf7460 r15=0000000000000048
iopl=0 nv up ei ng nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000282
NSI!NsiIoctl+0x1af:
00007fff`017021bf 25000000c0 and eax,0C0000000h

setting the same with startport 1 seems to succed

further google says CreatePersistentTcpPortReservation function (iphlpapi.h)

will return

ERROR_INVALID_PARAMETER An invalid parameter was passed to the function.

This error is returned if zero is passed in the StartPort or NumberOfPorts parameters. This error is also returned if the NumberOfPorts parameter is too large a block of ports depending on the StartPort parameter that the allocable block of ports would exceed the maximum port that can be allocated.

Thanks, this is useful as a comparison.

I agree that startport=0 is invalid for the public persistent/excluded port range interfaces. Your netsh test and the documented behavior of CreatePersistentTcpPortReservation are consistent with that.

However, what I am seeing in the failing system does not appear to be simply the same public API path.

In tcpip!AcquirePortReservationWithFlags, the code does not appear to treat a zero start port as an immediate invalid-parameter condition. After the range check it explicitly tests the start port and records whether it is zero:

lea     eax,[r14+r13]
cmp     eax,10000h
ja      ...STATUS_INVALID_PARAMETER

test    r14w,r14w
sete    dil

So the internal TCPIP reservation path appears to have special handling for StartPort == 0, rather than simply rejecting it in the same way as netsh / the public persistent reservation API.

More importantly, I have now captured another natural 4231 which did not go through TcpGlobalPortReservation at all.

For that incident:

TcpGlobalPortReservation = 0
Reservations             = 0

A kernel breakpoint caught the failure here:

tcpip!TcpBindEndpointRequestInspectComplete+0x51d
edi = 0xC0000209

with the stack:

tcpip!TcpBindEndpointRequestInspectComplete
tcpip!TcpBindEndpointWorkQueueRoutine
tcpip!TcpIoControlEndpoint
...
afd!AfdTLBind
afd!AfdBind

The disassembly shows that TcpBindEndpointRequestInspectComplete calls:

tcpip!InetAcquireWildcardPortUnderLock
mov edi,eax
test eax,eax
js   failure_path

So for this natural 4231, InetAcquireWildcardPortUnderLock() itself returned 0xC0000209.

I then disassembled InetAcquireWildcardPortUnderLock. It searches the internal port bitmap using RtlFindClearBits, and one of the exhaustion paths is:

call    nt!RtlFindClearBits
cmp     eax,0FFFFFFFFh
je      exhaustion_path

The function initializes/returns 0xC0000209 on that path and eventually calls:

tcpip!InetLogThrottledPortPoolEvent

which is the routine that writes the throttled System event.

So at this point I think there may be at least two separate internal failure paths:

  1. the earlier TcpGlobalPortReservation / 0xC000000D path, where StartPort=0 is involved;
  2. a direct wildcard-port allocation failure where InetAcquireWildcardPortUnderLock() returns 0xC0000209, with no TcpGlobalPortReservation event at all.

The second path is now confirmed with a live kernel breakpoint on a naturally occurring 4231.

I am currently tracing InetLogThrottledPortPoolEvent as a possible common point for both 4231 and 4266, and waiting for the next natural occurrence.