Repository navigation
Description
Windows Version
Windows 11 (retail channel), OS Build 10.0.26300.9457, fse.sys 10.0.26100.9278
WSL Version
WSL 3.0.2.0 (also reproduced with 3.0.1.0), kernel 6.18.40.1-1, WSL 2
Are you using WSL 1 or WSL 2?
WSL 2
Summary
networkingMode=Mirrored fails with CreateInstance/CreateVm/ConfigureNetworking/0x8007054f and falls back to networkingMode=None (no network at all in the guest). We traced the failure to a single host-side call: HcnReserveGuestNetworkServicePortRange cannot satisfy the hardcoded 4095-port contiguous reservation because WinNAT's runtime port exclusions fragment the host's dynamic port range. The failure is deterministic within a boot and varies across boots ("boot lottery"), which explains the intermittent reports on this error code.
Root cause analysis
1. Event log timeline (Microsoft-Windows-Host-Network-Service-Operational, events 1053/1054/1055) — the GuestNetworkService is created and torn down within ~23 ms, and HNS logs no error at all:
19:29:53.171 Create GuestNetworkService (MirrorHostNetworking:true, SchemaVersion 2.0)
19:29:53.173 Modify GuestNetworkService -> Bootstrapping (succeeds)
19:29:53.174 Query GuestNetworkService -> State:2, IsFseSelfManaged:true
19:29:53.197 Delete GuestNetworkService <- teardown
2. Source path: In src/windows/service/exe/MirroredNetworking.cpp, Initialize() calls CreateGuestNetworkService() (the Create/Modify/Query triple above), then immediately:
m_ephemeralPortRange = m_guestNetworkService.AllocateEphemeralPortRange();which in src/windows/service/exe/WslCoreGuestNetworkService.cpp does:
static constexpr auto c_ephemeralPortRangeSize = 4095;
THROW_IF_FAILED(m_allocatePortRange.value()(m_service.get(), c_ephemeralPortRangeSize, &m_reservedPortRange, &port));The exception propagates, GuestNetworkService::Stop() deletes the GNS, and the whole mirrored configuration surfaces as an opaque 0x8007054f.
3. Direct API repro (PowerShell P/Invoke against computenetwork.dll, no WSL involved):
Add-Type @'
using System;
using System.Runtime.InteropServices;
public static class HcnTest {
[DllImport("computenetwork.dll", CharSet = CharSet.Unicode)]
public static extern int HcnCreateGuestNetworkService(ref Guid Id, string Settings, out IntPtr Service, out IntPtr Error);
[DllImport("computenetwork.dll")]
public static extern int HcnReserveGuestNetworkServicePortRange(IntPtr Service, uint PortCount, out uint StartPort, out uint EndPort, out IntPtr PortReservation);
[DllImport("computenetwork.dll", CharSet = CharSet.Unicode)]
public static extern int HcnDeleteGuestNetworkService(ref Guid Id, out IntPtr Error);
}
'@
$id = [Guid]::NewGuid()
$settings = '{"VirtualMachineId":"' + $id + '","MirrorHostNetworking":true,"SchemaVersion":{"Major":2,"Minor":0},"Flags":3}'
$svc = [IntPtr]::Zero; $err = [IntPtr]::Zero
[HcnTest]::HcnCreateGuestNetworkService([ref]$id, $settings, [ref]$svc, [ref]$err) # -> 0x0
$s=[uint32]0;$e=[uint32]0;$h=[IntPtr]::Zero
[HcnTest]::HcnReserveGuestNetworkServicePortRange($svc, 4095, [ref]$s, [ref]$e, [ref]$h) # -> 0x8007054F <-- the exact error
[HcnTest]::HcnReserveGuestNetworkServicePortRange($svc, 2047, [ref]$s, [ref]$e, [ref]$h) # -> 0x0 (succeeds)
[HcnTest]::HcnDeleteGuestNetworkService([ref]$id, [ref]$err)On the affected host, 4095 ports always fails with 0x8007054f, smaller sizes succeed.
4. Why the port space is fragmented: the host's TCP dynamic port range had been reconfigured to 1024-60000 (traced to the legacy HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\MaxUserPort = 60000 value) while UDP remained at the default 49152-65535. WinNAT reserves multiple random ~100-port blocks at each boot. With the TCP∩UDP intersection reduced to 49152-60000 (~10.8k ports), the exclusions left no contiguous 4095-port window:
$ netsh int ipv4 show excludedportrange protocol=udp (fragmented state)
50000-50059, 51912-52411 (5 blocks), 53935-54034, 56206-56305
-> largest free contiguous window: 3695 < 4095
Since WinNAT re-randomizes its blocks every boot, mirrored networking works on some boots and fails on others — matching the "sometimes a reboot fixes it" pattern seen in #13454 / #13587 / #12470 / #41228.
Third-party drivers were ruled out on this host (stopping Sangfor/VMware/Hikvision network filter drivers changed nothing).
Fix / workaround (verified)
netsh int ipv4 set dynamicport tcp start=49152 num=16384
netsh int ipv6 set dynamicport tcp start=49152 num=16384
reg delete "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v MaxUserPort /f
net stop winnat && net start winnat
wsl --shutdownAfter this, HcnReserveGuestNetworkServicePortRange(4095) returns S_OK and mirrored networking comes up (mirrored eth0, default route, DNS, outbound 200s).
Suggestions
- Surface an actionable error.
0x8007054f(ERROR_INTERNAL_ERROR) from a port-range allocation tells the user nothing, and HNS logs no failure event. A specific error/warning (e.g. "could not reserve 4095 contiguous ports in dynamic port range") would have saved days of forensics. - Degrade gracefully. Retrying with a smaller range, or composing the reservation out of multiple smaller ranges, would keep mirrored networking functional instead of dropping to
None. - Consider a
.wslconfigknob for the ephemeral port-range size.
Related issues
Same error-code cluster: #41228 (26300, closed unresolved), #41251 (26200, HypervisorPlatform case), #13454, #13587, #12470. #41398 is a different failure stage (VmSwitch veto 0xc0010022) but same FSE/GNS subsystem.
Activity
github-actions commentedon Oct 6, 2026
Logs are required for review from WSL team
If this a feature request, please reply with '/feature'. If this is a question, reply with '/question'.
Otherwise, please attach logs by following the instructions below, your issue will not be reviewed unless they are added. These logs will help us understand what is going on in your machine.
How to collect WSL logs
Download and execute collect-wsl-logs.ps1 in an administrative powershell prompt:
The script will output the path of the log file once done.
If this is a networking issue, please use
.\collect-wsl-logs.ps1 -LogProfile networkinginstead, following the instructions in Collect WSL logs for networking issuesOnce completed please upload the output files to this GitHub issue.
See Collect WSL logs (recommended method).
If you choose to email these logs instead of attaching them to the bug, please send them to [email protected] with the GitHub issue number in the subject, and include a link to your GitHub issue comment in the message body, and reply with '/emailed-logs'.
annis-souames commentedon Oct 16, 2026
Thanks a lot for this detailed report! I was struggling with this issue for MONTHS and restarting HNS solved the issues only 40-50% of the time.
Thanks to this report, I tried resetting my TCP port range because it was abnormally large and the issue seems to have disappeared for now. Several issues have been raised about this, WSL seriously needs a patch for this.
LegaSage commentedon Oct 20, 2026
Related data point from the other side of the same reservation: when it succeeds, the window it picks swallows ports host apps rely on, and nothing on the host can steer it.
WSL 2.7.3.0, kernel 6.6.114.1-1, Windows 10.0.26300.9711,
networkingMode=mirrored. Measured by bind-scanning 30000–49599 from the host and readingip_local_port_rangein the guest:ip_local_port_range)So it tries 44620–48715 first and steps down by 1365 past any window containing an in-use port. Inside the window a host
bind()fails withEADDRINUSE. Nothing appears innetstat/Get-NetTCPConnection, and the range is not listed innetsh int ipv4 show excludedportrange.Two things an app developer can't work around:
netsh int ipv4 add excludedportrange protocol=tcp startport=48477 numberofports=1was in place, and 48477 was still reserved afterwsl --shutdownand a restart.net.ipv4.ip_local_port_rangein the guest (/etc/sysctl.d) doesn't move the host-side reservation. The guest used the new range while the host still withheld 44620–48715, which also leaves the guest's ephemeral ports un-reserved on the host.Apps with a default port in 44620–48715 fail on every mirrored-mode host. We hit it on 48477; another project hit 48666 (vinzdg/codenotch#443). A
.wslconfigsetting for the reserved range (start, or start + size), or honouring administered exclusions, would fix both this and the fragmentation failure above.doctor: KVM001, BIN001 and NET005 from the WSL 3.0.x issues (#121)
bkataru commentedon Oct 29, 2026
Confirming the mechanism on a second host, with a test that controls for whether the dynamic-port setting is actually live.
Environment: Windows 10.0.26200.9168, WSL 2.7.13.0, kernel 6.18.33.2-2,
networkingMode=mirrored, single Wi-Fi uplink.Building on LegaSage's finding above (44620–48715 → 1365 step-down), I can reproduce all four of my observations on the same lattice:
start ≡ 940 (mod 1365),1365 = 4095/3, anchored at 56905 →43255(k=10),29605(k=20),28240(k=21),21415(k=26). Credit for the stride goes to that comment; the extra point here is that it holds across many boots on this host too.Controlled test (the part I think adds something). Earlier in my debugging I convinced myself the dynamic range was irrelevant, because mirrored succeeded with
dynamicport tcp start=50000 num=1000. That conclusion was wrong — I had not verified the setting was live. Changingnetsh int ipv4 set dynamicportdoes take effect immediately on this build (no reboot), which can be verified by opening outbound connections and reading the local ports:With the setting proven live, the results are unambiguous:
1024 + 64511(original)30000 + 2100020000 + 1000So the 4095-port reservation must fit inside the dynamic TCP range, exactly as the OP describes. My "contradiction" was measurement error, not a different mechanism — worth stating explicitly in case anyone else runs a similarly sloppy version of this test.
Practical consequence: the failure is predictable before booting. If no
56905 - 1365kwindow (k = 0..40, size 4096) fits entirely inside[dynamicport start, dynamicport start + num), the next start will fail with0x8007054fand fall back tonetworkingMode=None.One negative result, consistent with LegaSage's item 1: administering
excludedportrangeover the exact window WSL had just chosen did not move it. I could not separate "exclusions are ignored" from "exclusion needs a reboot to take effect", so I am not claiming the stronger version. Documenting whether administered exclusions are consulted would settle it.Finally, one observation that may be useful for triage: on this host no
0x8007054fappears in any Windows event log. HNS Admin logs every guest-network-service create/remove asResult code = '0x0'right through the failure; the HRESULT only surfaces on WSL's stderr. That matches the request in the Suggestions section for an actionable error.DBinK commentedon Nov 9, 2026
Additional reproduction on WSL 3.0.3: a temporary UDP bind triggers the failure
This is additional evidence for this issue, not a report of a regression in #41880. I have not tested a version containing that fix.
Environment
[wsl2] networkingMode=mirrored,dnsTunneling=trueObserved failure
Starting WSL with the relevant host port occupied produced:
wslinfo --networking-modereturnednone, and Linux had only its loopback interface.Controlled reproduction and recovery
On this host, binding UDP port 41641 on both IPv4 and IPv6 is sufficient to reproduce the failure. No traffic needs to be sent, and no adapter or security software needs to be disabled.
wsl --shutdown, then start the distribution and querywslinfo --networking-mode.0x8007054fand modenone.wsl --shutdownand start the distribution again.mirrored; an outbound HTTPS request returns HTTP 200.This is host-state-dependent: port 41641 is not claimed to be a universal trigger. Other existing allocations on this machine determine whether this extra bind prevents the larger allocation. Keeping Tailscale running without this particular binding did not, by itself, reproduce the failure.
Direct HCN API checks
Separate probes using a temporary guest network service returned:
0x8007054F0x000000000x00000000Reservation handles and temporary guest network services were released/deleted after the probes. One important limitation: a separate 4095-port probe also failed while an already-working mirrored setup could restart successfully, so an independent probe is not treated as a complete predictor of WSL startup.
Relationship to the merged fix
#41880, commit
48aefbb2b6bba28dba32187fd228c1e788207261, adds the smaller-range fallback and warnings. I verified that the 3.0.4 prerelease source contains it, but this machine remains on 3.0.3; the fix has not been validated here.The reversible UDP-bind reproduction above may be useful as additional evidence or a regression-test scenario. It also shows why this symptom should not automatically be attributed to a Tailscale driver defect: an ordinary Python UDP bind reproduced the same startup failure, and releasing it restored mirrored networking.