Skip to content

Connections to a secondary loopback alias crash or hang on macOS 26 + .NET 10 (apphost launch only) #130284

Description

@pieter-venter-wd

Description

On macOS 26.5.2 (Darwin 25.5.0), when an app is launched via the apphost (dotnet run, a
JetBrains Rider "Run" configuration, or executing the built apphost binary directly — i.e. not
via dotnet <path-to-dll> through the shared framework host), incoming connections that target a
secondary loopback alias (an address added to lo0 via e.g. sudo ifconfig lo0 alias 10.100.100.101) are broken. Genuine 127.0.0.1 / ::1 always work fine.

The exact symptom depends on how the Kestrel listener is bound:

Kestrel binding 127.0.0.1 Secondary loopback alias (e.g. 10.100.100.101)
options.ListenAnyIP(5000) (dual-stack IPv6Any + DualMode) OK Process crashes on accept
options.Listen(IPAddress.Any, 5000) (IPv4-only) OK Connection silently dropped, no crash

Neither symptom reproduces via a raw dotnet <path-to-dll> exec (through the shared framework
host) — only via the apphost. Neither reproduces on .NET 8, on the same machine and launch method.

Full write-up, exact reproduction matrix, and a minimal repro project:
https://github.com/pieter-venter-wd/kestrel-macos-bug

Reproduction steps

  1. sudo ifconfig lo0 alias 10.100.100.101
  2. Clone https://github.com/pieter-venter-wd/kestrel-macos-bug, open KestrelIssue.sln
  3. cd KestrelIssue && dotnet run
  4. In another terminal: curl -v http://10.100.100.101:5000/weatherforecast
  5. Observe the process crash (with the default options.ListenAnyIP(5000) binding) or an empty
    reply with the process still alive (if switched to options.Listen(IPAddress.Any, 5000))

Compare against:

  • curl -v http://127.0.0.1:5000/weatherforecast — works fine, either binding
  • Running dotnet bin/Debug/net10.0/KestrelIssue.dll directly instead of dotnet run, then
    repeating step 4 against the alias — works fine, either binding
  • Switching TargetFramework to net8.0 and repeating steps 3–4 — works fine, either binding

Expected behavior

Connections to a secondary loopback alias should behave the same as connections to 127.0.0.1.

Actual behavior

With a dual-stack ListenAnyIP binding, accepting the connection throws an unhandled exception
on a ThreadPool worker thread inside the socket accept completion callback, crashing the process:

System.ArgumentException: The supplied System.Net.SocketAddress is an invalid size for the
System.Net.IPEndPoint end point. (Parameter 'socketAddress')
at System.Net.IPEndPoint.Create(SocketAddress socketAddress)
at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSyncSuccess(Int32 bytesTransferred, SocketFlags flags)
at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationAsyncSuccess(Int32 bytesTransferred, SocketFlags flags)
at System.Net.Sockets.SocketAsyncEventArgs.AcceptCompletionCallback(IntPtr acceptedFileDescriptor, Memory`1 socketAddress, SocketError socketError)
at System.Net.Sockets.SocketAsyncEngine.System.Threading.IThreadPoolWorkItem.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
at System.Threading.Thread.StartCallback()

With an IPv4-only Listen(IPAddress.Any, ...) binding instead, the process does not crash, but the
connection is silently dropped: the TCP handshake completes, the HTTP request is sent and received,
and then the connection closes immediately with zero response bytes (curl: (52) Empty reply from server, within tens of milliseconds — not a timeout). Nothing is logged even with
Microsoft.AspNetCore.Server.Kestrel set to Debug/Trace.

Regression?

Yes — does not reproduce on .NET 8 with the same OS, machine, and launch method.

Known workarounds

  • None found for full connectivity. Targeting net8.0 instead of net10.0 avoids both symptoms
    entirely.
  • Binding IPv4-only avoids the crash but does not restore connectivity — it only trades the crash
    for a silent connection drop.

Configuration

  • .NET SDK 10.0.301 / runtime 10.0.9
  • macOS 26.5.2 (Darwin 25.5.0), Apple Silicon (arm64)

Other information

Reproduced with both the .NET 10 SDK's default minimal-API project template
(Microsoft.AspNetCore.OpenApi) and a stripped-down Kestrel-only app with zero extra
dependencies — not specific to any package.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions