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

  1. Retry freeport.TCP() once; a transient stack oddity may resolve itself.
  2. Check that the Go runtime and OS are standard (no unusual network stack shims); upgrade Go to a current patch release.
  3. If reproducible, file a bug with GOOS/GOARCH and Go version; the type assertion expectation is a stdlib invariant.
  4. 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

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


AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/468e0458e03e880b. Report an issue: GitHub.