gastownhall/beads · error
ensureProxiedServerConfig: pick free port: %w
Error message
ensureProxiedServerConfig: pick free port: %w
What it means
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.
Source
Thrown at cmd/bd/proxied_server.go:150
}
return path, nil
}
root := filepath.Dir(path)
if err := os.MkdirAll(root, config.BeadsDirPerm); err != nil {
return "", fmt.Errorf("ensureProxiedServerConfig: mkdir %s: %w", root, err)
}
switch _, err := os.Stat(path); {
case err == nil:
return path, nil
case !os.IsNotExist(err):
return "", fmt.Errorf("ensureProxiedServerConfig: stat %s: %w", path, err)
}
port, err := proxy.PickFreePort()
if err != nil {
return "", fmt.Errorf("ensureProxiedServerConfig: pick free port: %w", err)
}
body, err := renderProxiedServerConfig(port)
if err != nil {
return "", fmt.Errorf("ensureProxiedServerConfig: render YAML: %w", err)
}
if err := atomicWriteFile(resolveConfigWriteTarget(path), body); err != nil {
return "", fmt.Errorf("ensureProxiedServerConfig: write %s: %w", path, err)
}
return path, nil
}
// resolveConfigWriteTarget resolves path to its physical location before
// an atomic rewrite. os.Rename's destination argument does not follow
// symlinks — it unlinks and replaces whatever is AT that path, symlink or
// not — so writing straight to a symlinked config.yaml would silently
// replace the symlink itself with a regular file instead of updating the
// file it points at. Falls back to path unresolved when it does not existView on GitHub (pinned to 71377f2769)
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.
Example fix
// before (host exhausted ephemeral ports) sysctl net.ipv4.ip_local_port_range="32768 32799" # too narrow // after sudo sysctl -w net.ipv4.ip_local_port_range="1024 65535"
Defensive patterns
Strategy: retry
Validate before calling
func canBindLoopback() error {
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return err
}
l.Close()
return nil
} Try / catch
port, err := proxy.PickFreePort()
if err != nil {
if isEphemeralPortExhaustion(err) { // check ss -s / TIME_WAIT count
time.Sleep(2 * time.Second)
port, err = proxy.PickFreePort()
}
if err != nil {
return fmt.Errorf("no free port available: %w", err)
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- accept: %w
- server: DoltServer.Dial: %w
- server: ExternalDoltServer.Dial: %w
- failed to remove backup: %w
- ensureProxiedServerConfig: custom config %s: not a regular f
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d1748fc9b7dbae0c.
Report an issue: GitHub.