derailed/k9s · error
port %s is not available on host
Error message
port %s is not available on host
What it means
PFAnns.ToTunnels builds one host tunnel per parsed annotation and, before accepting it, asks the injected PortChecker (which wraps IsPortFree, a net.Listen bind test) whether address:LocalPort can be bound. The error means the local port is already taken on the host, so a port-forward would fail.
Source
Thrown at internal/port/pfs.go:44
}
}
if a.LocalPort != "" {
lps = append(lps, a.LocalPort)
}
}
return strings.Join(specs, ","), strings.Join(lps, ",")
}
func (aa PFAnns) ToTunnels(address string, _ ContainerPortSpecs, available PortChecker) (PortTunnels, error) {
pts := make(PortTunnels, 0, len(aa))
for _, a := range aa {
pt, err := a.ToTunnel(address)
if err != nil {
return pts, err
}
if !available(context.Background(), pt) {
return pts, fmt.Errorf("port %s is not available on host", pt.LocalPort)
}
pts = append(pts, pt)
}
return pts, nil
}
// ParsePFs hydrates a collection of portforward annotations.
func ParsePFs(ann string) (PFAnns, error) {
ss := strings.Split(ann, ",")
pp := make(PFAnns, 0, len(ss))
for _, s := range ss {
f, err := ParsePF(s)
if err != nil {
return nil, err
}
pp = append(pp, f)
}View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Free the port: lsof -ti :<port> | xargs kill (or stop the local service using it)
- Change the local port in the annotation, e.g. '8080:80' -> '18080:80'
- Stop the duplicate port-forward in k9s (port-forward view, Ctrl-D / delete) before starting another
- Bind to a different address or pick an ephemeral high port that nothing else uses
Example fix
# before: local 8080 already in use k9scli.io/port-forwards: "myapp::8080:80" # after: remap to free local port k9scli.io/port-forwards: "myapp::18080:80"
Defensive patterns
Strategy: fallback
Validate before calling
// Pre-check each local port before building tunnels:
if !port.IsPortFree(ctx, port.NewPortTunnel("127.0.0.1", "", localPort, "")) {
localPort = nextFreePort(localPort) // pick 18080, 18081, ...
} Try / catch
On 'port %s is not available on host', free the port or remap the local port and rebuild PFAnns with the substituted value; treat as retryable-with-change, not retry-as-is.
Prevention
- Use high ephemeral local ports (>20000) in annotations to avoid common service ranges
- Check lsof/ss for the intended local port before starting k9s sessions
- Avoid forwarding the same resource twice; close stale tunnels from the port-forward view
When it happens
Trigger: Forwarding the same pod/service twice in one k9s session; a local dev server already listening on the annotation's local port; a stale k9s process holding the port; two annotations claiming the same local port.
Common situations: Fixed local ports in k9scli.io/port-forwards colliding with local services (e.g. 3000, 8080, 5000 on macOS where AirPlay listens); resuming a session whose tunnels were never torn down; Docker/other container runtimes bound to the same port.
Related errors
- port %s is not available on host
- no exposed ports
- no port number assigned
- unable to connect to context %q
- failed to maintain log stream after %d retries
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/8908120c2e425730.
Report an issue: GitHub.