lima-vm/lima · error
expected *net.TCPAddr, got %v
Error message
expected *net.TCPAddr, got %v
What it means
freeport.TCP() binds a listener on 127.0.0.1:0 and asserts that the returned address is a *net.TCPAddr so it can read the assigned port. If net.Listener.Addr() ever returns something other than *net.TCPAddr for a TCP listener, this error fires. In practice this is a defensive invariant check and should be unreachable on supported platforms.
Source
Thrown at pkg/freeport/freeport.go:25
import (
"fmt"
"net"
)
func TCP() (int, error) {
lAddr0, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:0")
if err != nil {
return 0, err
}
l, err := net.ListenTCP("tcp4", lAddr0)
if err != nil {
return 0, err
}
defer l.Close()
lAddr := l.Addr()
lTCPAddr, ok := lAddr.(*net.TCPAddr)
if !ok {
return 0, fmt.Errorf("expected *net.TCPAddr, got %v", lAddr)
}
port := lTCPAddr.Port
if port <= 0 {
return 0, fmt.Errorf("unexpected port %d", port)
}
return port, nil
}
func UDP() (int, error) {
lAddr0, err := net.ResolveUDPAddr("udp4", "127.0.0.1:0")
if err != nil {
return 0, err
}
l, err := net.ListenUDP("udp4", lAddr0)
if err != nil {
return 0, err
}
defer l.Close()View on GitHub (pinned to dd909d0973)
Solutions
- Retry freeport.TCP() once; a transient stack oddity may resolve itself.
- Check that the Go runtime and OS are standard (no unusual network stack shims); upgrade Go to a current patch release.
- If reproducible, file a bug with GOOS/GOARCH and Go version; the type assertion expectation is a stdlib invariant.
- As a workaround, allocate the port manually with net.Listen("tcp", "127.0.0.1:0") and handle the address type yourself.
Example fix
// before
port, err := freeport.TCP()
if err != nil { return err }
// after
port, err := freeport.TCP()
if err != nil {
// defensive: fall back to manual allocation
l, lerr := net.Listen("tcp", "127.0.0.1:0")
if lerr != nil { return err }
port = l.Addr().(*net.TCPAddr).Port
l.Close()
} Defensive patterns
Strategy: try-catch
Type guard
if tcpAddr, ok := l.Addr().(*net.TCPAddr); !ok { return 0, fmt.Errorf("expected *net.TCPAddr, got %v", l.Addr()) } Try / catch
port, err := freeport.TCP()
if err != nil {
// fallback: allocate manually
l, lerr := net.Listen("tcp", "127.0.0.1:0")
if lerr != nil { return fmt.Errorf("freeport.TCP failed: %w: %v", err, lerr) }
defer l.Close()
port = l.Addr().(*net.TCPAddr).Port
} Prevention
- Keep the Go toolchain current to avoid stdlib regressions
- Avoid wrapping listeners with custom net.Addr implementations
- Retry once on transient allocation failures
When it happens
Trigger: Calling freeport.TCP() when the runtime's network stack returns a non-TCPAddr implementation of net.Addr from l.Addr(), e.g. an exotic build, a custom netgo override, or a mocked/unknown network interface type.
Common situations: Practically never seen in the wild; it surfaces during runtime-behavior changes (Go stdlib regressions, unusual OS network layers, sandboxed environments) or when code is refactored so a non-TCP listener feeds the same path.
Related errors
- expected *net.UDPAddr, got %v
- unexpected port %d
- network %#q already exists
- network mode %#q does not support specifying gateway
- network mode %#q requires specifying interface
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/468e0458e03e880b.
Report an issue: GitHub.