gastownhall/beads · error
proxy child exited before becoming ready on explicitly confi
Error message
proxy child exited before becoming ready on explicitly configured port %d (see %s): %w
What it means
Returned by spawnAndHandoff when the spawned proxy child exits before it became ready, and the caller explicitly configured a non-zero port via OpenOpts.Port. The child's own exit error is wrapped, and the error points at the child's log file because the real cause (port already in use, backend start failure, etc.) is recorded there.
Source
Thrown at internal/storage/dbproxy/proxy/endpoint.go:384
return Endpoint{}, ierr
} else if interrupted {
return Endpoint{}, fmt.Errorf("%w for %s", errStartInterrupted, rootDir)
}
if childErr == nil {
childErr = errors.New("child exited without reporting an error")
}
// A LockHeldExitCode exit is a lost spawn race, not a listen
// failure; any other exit gets the child's log path so the real
// error (listen, backend start, ...) is findable.
var exitErr *exec.ExitError
if errors.As(childErr, &exitErr) && exitErr.ExitCode() == LockHeldExitCode {
return Endpoint{}, fmt.Errorf(
"proxy child lost the proxy.lock spawn race for %s: %w",
rootDir, childErr,
)
}
if opts.Port != 0 {
return Endpoint{}, fmt.Errorf(
"proxy child exited before becoming ready on explicitly configured port %d (see %s): %w",
opts.Port, opts.LogFilePath, childErr,
)
}
return Endpoint{}, fmt.Errorf(
"proxy child exited before publishing its OS-assigned port (see %s): %w",
opts.LogFilePath, childErr,
)
case <-hard.C:
if err := killSpawnedChild(child); err != nil {
return Endpoint{}, fmt.Errorf("hard timeout waiting for proxy on %s; safe child kill failed: %w", describeSpawnPort(opts.Port), err)
}
return Endpoint{}, fmt.Errorf("hard timeout (%s) waiting for proxy on %s", spawnReadyHardTimeout, describeSpawnPort(opts.Port))
case <-poll.C:
}
if time.Now().After(deadline) {
if err := killSpawnedChild(child); err != nil {
return Endpoint{}, fmt.Errorf("timeout waiting for proxy on %s; safe child kill failed: %w", describeSpawnPort(opts.Port), err)View on GitHub (pinned to 71377f2769)
Solutions
- Read the child log at opts.LogFilePath — the wrapped error and log contain the actual startup failure.
- Check whether the configured port is already in use (lsof/ss) and free it or pick a different port.
- Set OpenOpts.Port to 0 to let the OS assign a free port and publish it via the discovery record.
- Verify the backend prerequisites (dolt binary path, config file) before spawning.
Example fix
// before: fixed port collides with an existing service
opts := OpenOpts{Port: 8337, LogFilePath: logPath}
// after: let the OS pick a free port and rely on port publication
opts := OpenOpts{Port: 0, LogFilePath: logPath} Defensive patterns
Strategy: validation
Validate before calling
if opts.Port != 0 {
ln, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", opts.Port))
if err != nil { return fmt.Errorf("configured port %d unavailable: %w", opts.Port, err) }
ln.Close()
} Try / catch
ep, err := GetCreateDatabaseProxyServerEndpoint(rootDir, opts)
if err != nil && strings.Contains(err.Error(), "exited before becoming ready on explicitly configured port") {
log.Printf("proxy failed on port %d; see %s", opts.Port, opts.LogFilePath)
opts.Port = 0 // fall back to OS-assigned port
ep, err = GetCreateDatabaseProxyServerEndpoint(rootDir, opts)
} Prevention
- Leave Port at 0 (OS-assigned) unless a fixed port is required
- Before pinning a port, check it is free with net.Listen
- Always set LogFilePath so child failures are diagnosable
- Kill stale proxies from previous runs before reusing a port
When it happens
Trigger: GetCreateDatabaseProxyServerEndpoint is called with OpenOpts.Port set to a specific value and the child dies during startup — e.g. bind fails because the port is occupied, the Dolt backend fails to start, or the child crashes on config loading.
Common situations: Config file pins a proxy port that another service already uses; leftover process from a previous run still listening on the pinned port; SELinux/firewall or container restrictions blocking the bind; bad --dolt-bin path crashing the backend.
Related errors
- dolt sql-server exited before listener became ready
- proxy child exited before publishing its OS-assigned port (s
- hard timeout (%s) waiting for proxy on %s
- proxy child lost the proxy.lock spawn race for %s: %w
- hard timeout waiting for proxy on %s; safe child kill failed
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ed12fa27a3340009.
Report an issue: GitHub.