gastownhall/beads · error
allocating ephemeral port: %w
Error message
allocating ephemeral port: %w
What it means
allocateEphemeralPort asks the kernel for a free TCP port by binding to host:0 via net.Listen, reading the assigned port, and closing the listener. This error wraps any net.Listen failure while obtaining that ephemeral port, so Start() cannot proceed to launch dolt sql-server.
Source
Thrown at internal/doltserver/doltserver.go:388
func pidPath(beadsDir string) string { return filepath.Join(beadsDir, PIDFileName) }
func logPath(beadsDir string) string { return filepath.Join(beadsDir, "dolt-server.log") }
func lockPath(beadsDir string) string { return filepath.Join(beadsDir, "dolt-server.lock") }
func portPath(beadsDir string) string { return filepath.Join(beadsDir, PortFileName) }
// MaxDoltServers is the hard ceiling on concurrent dolt sql-server processes.
// Allows up to 3 (e.g., multiple projects).
func maxDoltServers() int {
return 3
}
// allocateEphemeralPort asks the OS for a free TCP port on host.
// It binds to port 0, reads the assigned port, and closes the listener.
// The caller should pass the returned port to dolt sql-server promptly
// to minimize the TOCTOU window.
func allocateEphemeralPort(host string) (int, error) {
ln, err := net.Listen("tcp", net.JoinHostPort(host, "0"))
if err != nil {
return 0, fmt.Errorf("allocating ephemeral port: %w", err)
}
port := ln.Addr().(*net.TCPAddr).Port
_ = ln.Close()
return port, nil
}
// isPortAvailable checks if a TCP port is available for binding.
func isPortAvailable(host string, port int) bool {
addr := net.JoinHostPort(host, strconv.Itoa(port))
ln, err := net.Listen("tcp", addr)
if err != nil {
return false
}
_ = ln.Close()
return true
}
// reclaimPort ensures an explicit (user-configured) port is available for use.View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped net error (e.g. 'lookup host: no such host', 'cannot assign requested address')
- Verify the configured host is a local interface or empty string for all interfaces
- Use 127.0.0.1 or 'localhost' instead of an unresolvable/remote hostname
- If using IPv6, confirm the host supports it (ip -6 addr) or switch to IPv4
- Check firewall/SELinux rules that may block TCP binds
Example fix
// before: host set to a remote machine export BEADS_DOLT_SERVER_HOST=db.internal.example.com // after: bind locally; point clients at the remote host explicitly export BEADS_DOLT_SERVER_HOST=127.0.0.1
Defensive patterns
Strategy: retry
Validate before calling
// Pre-check that the host is bindable locally
host := os.Getenv("BEADS_DOLT_SERVER_HOST")
if host != "" && net.ParseIP(host) != nil {
addrs, _ := net.InterfaceAddrs()
found := false
for _, a := range addrs {
if strings.HasPrefix(a.String(), host+"/") { found = true }
}
if !found && host != "127.0.0.1" && host != "::1" {
// host is not a local interface — bind will likely fail
}
} Try / catch
port, err := doltserver.Start(beadsDir)
if err != nil && strings.Contains(err.Error(), "allocating ephemeral port") {
// retry once, or fall back to default host
os.Unsetenv("BEADS_DOLT_SERVER_HOST")
port, err = doltserver.Start(beadsDir)
} Prevention
- Leave BEADS_DOLT_SERVER_HOST unset or use 127.0.0.1 unless you know the interface exists
- Verify IPv6 support before configuring an IPv6 bind host
- In sandboxes/CI, confirm socket creation is permitted
- Keep the TOCTOU window small: start the server promptly after allocation
When it happens
Trigger: Start() calling allocateEphemeralPort(host) where net.Listen("tcp", host:0) fails — host resolves to an address with no local interface, IPv6 host on a machine without IPv6 support, or restrictive firewall/SELinux policy blocking socket bind.
Common situations: BEADS_DOLT_SERVER_HOST configured to a hostname that doesn't resolve locally or to a remote host, hosts with IPv6 disabled receiving an IPv6 bind address, sandboxed CI runners denying socket creation.
Related errors
- listen on %s: %w
- ensureProxiedServerConfig: pick free port: %w
- bind %s: %w
- identity: dial control listener: %w
- identity: write request: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0730b2652094012f.
Report an issue: GitHub.