{"record":{"id":"468e0458e03e880b","repo":"lima-vm/lima","slug":"expected-net-tcpaddr-got-v","errorCode":null,"errorMessage":"expected *net.TCPAddr, got %v","messagePattern":"expected \\*net\\.TCPAddr, got (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/freeport/freeport.go","lineNumber":25,"sourceCode":"import (\n\t\"fmt\"\n\t\"net\"\n)\n\nfunc TCP() (int, error) {\n\tlAddr0, err := net.ResolveTCPAddr(\"tcp4\", \"127.0.0.1:0\")\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tl, err := net.ListenTCP(\"tcp4\", lAddr0)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tdefer l.Close()\n\tlAddr := l.Addr()\n\tlTCPAddr, ok := lAddr.(*net.TCPAddr)\n\tif !ok {\n\t\treturn 0, fmt.Errorf(\"expected *net.TCPAddr, got %v\", lAddr)\n\t}\n\tport := lTCPAddr.Port\n\tif port <= 0 {\n\t\treturn 0, fmt.Errorf(\"unexpected port %d\", port)\n\t}\n\treturn port, nil\n}\n\nfunc UDP() (int, error) {\n\tlAddr0, err := net.ResolveUDPAddr(\"udp4\", \"127.0.0.1:0\")\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tl, err := net.ListenUDP(\"udp4\", lAddr0)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tdefer l.Close()","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/freeport/freeport.go#L7-L43","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nport, err := freeport.TCP()\nif err != nil { return err }\n// after\nport, err := freeport.TCP()\nif err != nil {\n    // defensive: fall back to manual allocation\n    l, lerr := net.Listen(\"tcp\", \"127.0.0.1:0\")\n    if lerr != nil { return err }\n    port = l.Addr().(*net.TCPAddr).Port\n    l.Close()\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"if tcpAddr, ok := l.Addr().(*net.TCPAddr); !ok { return 0, fmt.Errorf(\"expected *net.TCPAddr, got %v\", l.Addr()) }","tryCatchPattern":"port, err := freeport.TCP()\nif err != nil {\n    // fallback: allocate manually\n    l, lerr := net.Listen(\"tcp\", \"127.0.0.1:0\")\n    if lerr != nil { return fmt.Errorf(\"freeport.TCP failed: %w: %v\", err, lerr) }\n    defer l.Close()\n    port = l.Addr().(*net.TCPAddr).Port\n}","preventionTips":["Keep the Go toolchain current to avoid stdlib regressions","Avoid wrapping listeners with custom net.Addr implementations","Retry once on transient allocation failures"],"tags":["network","freeport","type-assertion"],"backgroundTag":"unexpected-net-addr-type","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}