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

  1. Read the child log at opts.LogFilePath — the wrapped error and log contain the actual startup failure.
  2. Check whether the configured port is already in use (lsof/ss) and free it or pick a different port.
  3. Set OpenOpts.Port to 0 to let the OS assign a free port and publish it via the discovery record.
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/ed12fa27a3340009. Report an issue: GitHub.