Skip to content
Latchkey

ASP.NET Core Kestrel "Failed to bind to address ... address already in use" in CI

Kestrel could not bind because the TCP port is already held by another process, usually a leftover test host from a prior test or a hardcoded port shared by two parallel jobs. Bind to port 0 or a unique port.

What this error means

The web host throws "Failed to bind to address http://127.0.0.1:5000: address already in use" during startup, often in integration tests that spin up a real Kestrel server.

.NET
System.IO.IOException: Failed to bind to address http://127.0.0.1:5000:
address already in use.
 ---> Microsoft.AspNetCore.Connections.AddressInUseException: Address already in use

Diagnose it: SDK version and restore first

Most .NET CI failures are an SDK mismatch or a restore that did not happen. global.json pins the SDK, and if the runner does not have that exact version the failure message is about the project rather than the SDK.

Terminal
dotnet --info
cat global.json 2>/dev/null

# restore explicitly so a restore failure is not reported as a build failure
dotnet restore --verbosity normal
dotnet build --no-restore -warnaserror

Common causes

A hardcoded port shared across tests or jobs

Tests bind a fixed port like 5000. Two tests, or two matrix jobs on one runner, collide on the same port.

A leftover host from a previous test

A prior test started Kestrel and did not dispose the host, so the port is still occupied when the next test binds.

How to fix it

Bind to an ephemeral port

Ask the OS for a free port with :0, or let WebApplicationFactory use its in-memory TestServer that needs no real port at all.

Program.cs
builder.WebHost.UseUrls("http://127.0.0.1:0");

Dispose the host between tests

  1. Ensure each test disposes its WebApplicationFactory / host (use IDisposable / IAsyncDisposable).
  2. Prefer the in-memory TestServer over a real Kestrel bind for integration tests.
  3. Avoid a single fixed port shared by parallel test classes.

How to prevent it

  • Use TestServer (in-memory) instead of binding a real port in integration tests.
  • When a real port is needed, request port 0 so the OS assigns a free one.
  • Dispose hosts and factories so ports are released promptly.

Frequently asked questions

What causes ASP.NET core kestrel "Failed to bind to address ... address already in use" in CI?
There are 2 common causes: a hardcoded port shared across tests or jobs and a leftover host from a previous test. Tests bind a fixed port like 5000.
How do I fix ASP.NET core kestrel "Failed to bind to address ... address already in use" in CI?
There are 2 fixes depending on which cause you have: bind to an ephemeral port and dispose the host between tests. Work through them in order, since the first is the most common.
What does ASP.NET core kestrel "Failed to bind to address ... address already in use" in CI actually mean?
The web host throws "Failed to bind to address http://127.0.0.1:5000: address already in use" during startup, often in integration tests that spin up a real Kestrel server.
How do I stop ASP.NET core kestrel "Failed to bind to address ... address already in use" in CI happening again?
Use TestServer (in-memory) instead of binding a real port in integration tests. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card