gastownhall/beads · error

proxy child exited before publishing its OS-assigned port (s

Error message

proxy child exited before publishing its OS-assigned port (see %s): %w

What it means

Returned by spawnAndHandoff when the spawned proxy child exits before it publishes its OS-assigned port in the discovery record (i.e. OpenOpts.Port was 0). The error includes the child's log path so the underlying startup failure can be diagnosed.

Source

Thrown at internal/storage/dbproxy/proxy/endpoint.go:389

				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)
			}
			return Endpoint{}, fmt.Errorf("timeout waiting for proxy to become ready on %s", describeSpawnPort(opts.Port))
		}
	}
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the child log at opts.LogFilePath for the real startup error.
  2. Verify the workspace database opens cleanly (run the backend directly) and the config file parses.
  3. Check DoltBinPath points to a working dolt binary and that the workspace directory is writable.
  4. Re-run after clearing stale discovery/quarantine records under the workspace root if a previous crash left them behind.

Example fix

// before: silently relying on defaults hides backend misconfig
ep, err := GetCreateDatabaseProxyServerEndpoint(root, OpenOpts{})
// after: supply a log path so failures are diagnosable, and verify the backend first
ep, err := GetCreateDatabaseProxyServerEndpoint(root, OpenOpts{LogFilePath: filepath.Join(root, "proxy.log"), DoltBinPath: verifiedDoltPath})
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(doltBin); err != nil {
    return fmt.Errorf("dolt binary missing: %w", err)
}
if fi, err := os.Stat(rootDir); err != nil || !fi.IsDir() { return fmt.Errorf("bad workspace %q", rootDir) }

Try / catch

ep, err := GetCreateDatabaseProxyServerEndpoint(rootDir, opts)
if err != nil && strings.Contains(err.Error(), "exited before publishing its OS-assigned port") {
    log, rerr := os.ReadFile(opts.LogFilePath)
    log.Printf("proxy spawn failed; child log: %s (%v)", log, rerr)
}

Prevention

When it happens

Trigger: GetCreateDatabaseProxyServerEndpoint with OpenOpts.Port == 0 where the child dies during startup before writing its assigned port: backend start failure, database open error, config parse failure, or a crash.

Common situations: Missing or corrupt dolt database in the workspace; invalid --config file; wrong DoltBinPath; disk-full or permission problems preventing the child from writing its record; recent bd version change breaking the child invocation.

Related errors


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