{"record":{"id":"d1748fc9b7dbae0c","repo":"gastownhall/beads","slug":"ensureproxiedserverconfig-pick-free-port-w","errorCode":null,"errorMessage":"ensureProxiedServerConfig: pick free port: %w","messagePattern":"ensureProxiedServerConfig: pick free port: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/proxied_server.go","lineNumber":150,"sourceCode":"\t\t}\n\t\treturn path, nil\n\t}\n\n\troot := filepath.Dir(path)\n\tif err := os.MkdirAll(root, config.BeadsDirPerm); err != nil {\n\t\treturn \"\", fmt.Errorf(\"ensureProxiedServerConfig: mkdir %s: %w\", root, err)\n\t}\n\n\tswitch _, err := os.Stat(path); {\n\tcase err == nil:\n\t\treturn path, nil\n\tcase !os.IsNotExist(err):\n\t\treturn \"\", fmt.Errorf(\"ensureProxiedServerConfig: stat %s: %w\", path, err)\n\t}\n\n\tport, err := proxy.PickFreePort()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"ensureProxiedServerConfig: pick free port: %w\", err)\n\t}\n\n\tbody, err := renderProxiedServerConfig(port)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"ensureProxiedServerConfig: render YAML: %w\", err)\n\t}\n\tif err := atomicWriteFile(resolveConfigWriteTarget(path), body); err != nil {\n\t\treturn \"\", fmt.Errorf(\"ensureProxiedServerConfig: write %s: %w\", path, err)\n\t}\n\treturn path, nil\n}\n\n// resolveConfigWriteTarget resolves path to its physical location before\n// an atomic rewrite. os.Rename's destination argument does not follow\n// symlinks — it unlinks and replaces whatever is AT that path, symlink or\n// not — so writing straight to a symlinked config.yaml would silently\n// replace the symlink itself with a regular file instead of updating the\n// file it points at. Falls back to path unresolved when it does not exist","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/proxied_server.go#L132-L168","documentation":"When generating a fresh proxied-server config, bd must allocate a free TCP port for the proxy to listen on; this wraps a failure from proxy.PickFreePort. PickFreePort typically binds a listener on 127.0.0.1:0 and reads back the assigned port, so this error means the OS refused to allocate any ephemeral port at pick time.","triggerScenarios":"proxy.PickFreePort() fails: no available ephemeral ports (net.ipv4.ip_local_port_range exhausted, thousands of TIME_WAIT sockets), a security/seccomp or container policy forbidding bind(), or listen() on the wildcard/loopback blocked inside the sandbox.","commonSituations":"Long-lived CI machines leaking sockets until ephemeral ports run out; strict Docker/Kubernetes seccomp or AppArmor profiles; `net.ipv4.ip_local_port_range` misconfigured too narrow; proxies/VPN software exhausting ports; test suites opening thousands of parallel listeners.","solutions":["Check port exhaustion: `ss -s` (count of tcp sockets / TIME_WAIT) and widen or tune `net.ipv4.ip_local_port_range` via sysctl, or enable `net.ipv4.tcp_tw_reuse`.","Find and stop the process leaking sockets (`ss -tanp | awk '{print $6}' | sort | uniq -c`, then fix/kill the offender).","If inside a container/sandbox, confirm the seccomp/AppArmor/sandbox profile permits bind() on loopback; relax the profile or run the daemon on the host network namespace.","Retry after load subsides — the failure can be transient under heavy connection churn.","Restart the host or network namespace as a blunt reset when thousands of orphaned sockets cannot be reclaimed."],"exampleFix":"// before (host exhausted ephemeral ports)\nsysctl net.ipv4.ip_local_port_range=\"32768 32799\"   # too narrow\n// after\nsudo sysctl -w net.ipv4.ip_local_port_range=\"1024 65535\"","handlingStrategy":"retry","validationCode":"func canBindLoopback() error {\n\tl, err := net.Listen(\"tcp\", \"127.0.0.1:0\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tl.Close()\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"port, err := proxy.PickFreePort()\nif err != nil {\n\tif isEphemeralPortExhaustion(err) { // check ss -s / TIME_WAIT count\n\t\ttime.Sleep(2 * time.Second)\n\t\tport, err = proxy.PickFreePort()\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"no free port available: %w\", err)\n\t}\n}","preventionTips":["Monitor ephemeral port usage on long-lived CI machines (`ss -s`) and tune net.ipv4.ip_local_port_range.","Fix socket leaks in other services rather than letting TIME_WAIT accumulate.","Verify container seccomp/AppArmor profiles allow bind() on loopback before running bd daemons.","Cap concurrency of tools that open thousands of parallel TCP listeners on the same host."],"tags":["go","network","tcp","ports","proxied-server"],"backgroundTag":"no-free-port","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}