{"record":{"id":"4f3ff450377296f9","repo":"abiosoft/colima","slug":"error-closing-temporary-port-listener-w","errorCode":null,"errorMessage":"error closing temporary port listener: %w","messagePattern":"error closing temporary port listener: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"util/util.go","lineNumber":33,"sourceCode":"// HomeDir returns the user home directory.\nfunc HomeDir() string {\n\thome, err := os.UserHomeDir()\n\tif err != nil {\n\t\t// this should never happen\n\t\tlogrus.Fatal(fmt.Errorf(\"error retrieving home directory: %w\", err))\n\t}\n\treturn home\n}\n\n// RandomAvailablePort returns an available port on the host machine.\nfunc RandomAvailablePort() int {\n\tlistener, err := net.Listen(\"tcp\", \":0\")\n\tif err != nil {\n\t\tlogrus.Fatal(fmt.Errorf(\"error picking an available port: %w\", err))\n\t}\n\n\tif err := listener.Close(); err != nil {\n\t\tlogrus.Fatal(fmt.Errorf(\"error closing temporary port listener: %w\", err))\n\t}\n\n\treturn listener.Addr().(*net.TCPAddr).Port\n}\n\n// isPortAvailable checks if a specific port is available on the host.\nfunc isPortAvailable(port int) bool {\n\tlistener, err := net.Listen(\"tcp\", fmt.Sprintf(\":%d\", port))\n\tif err != nil {\n\t\treturn false\n\t}\n\tif err := listener.Close(); err != nil {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// FindAvailablePort finds the first available port starting from startPort.","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/abiosoft/colima/blob/c3a5f9184d83a197184f897a9f07eb3c01b3bc88/util/util.go#L15-L51","documentation":"RandomAvailablePort (util/util.go:33) closes its just-created throwaway listener and calls logrus.Fatal if Close returns an error, exiting the process. A close of a freshly bound listener essentially cannot fail unless the fd was already closed elsewhere (double close) or the kernel/network stack is in a faulted state. In practice this line is unreachable defensive code around fd lifecycle bugs.","triggerScenarios":"A double-close of the listener fd (a code bug, not a runtime condition), or pathological kernel/network-stack states where even close(2) errors; observable as an immediate FATAL during port setup.","commonSituations":"Almost none in stock colima; would surface in forks that refactor RandomAvailablePort and lose/re-close the listener; severe system-level fd table corruption after resource exhaustion.","solutions":["Rerun the command — a transient kernel state clears on retry","If it reproduces, audit code paths that took ownership of the listener for double-close bugs","Check `lsof | wc -l` against `ulimit -n` to rule out fd-table pressure","As a last resort reboot to reset the network stack state"],"exampleFix":"// before (fork bug: listener closed twice)\nport := listener.Addr().(*net.TCPAddr).Port\nlistener.Close()\nreturn port, listener // caller closes again -> fatal\n\n// after\nport := listener.Addr().(*net.TCPAddr).Port\nlistener.Close()\nreturn port, nil","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Close errors on a throwaway listener are transient; ignore-and-continue\n// is safe because the port number was already captured:\nport := listener.Addr().(*net.TCPAddr).Port\nif err := listener.Close(); err != nil {\n    log.Debugf(\"ignoring temp-listener close error: %v\", err)\n}","preventionTips":["Capture the port before closing; never let close failure discard it","Never share or double-close the listener fd across goroutines","Treat close errors on ephemeral diagnostic listeners as debug events, not fatals"],"tags":["network","fatal","file-descriptors","rare"],"backgroundTag":null,"analyzedSha":"c3a5f9184d83a197184f897a9f07eb3c01b3bc88","analyzedAt":"2026-08-15T18:58:08.334Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}