{"record":{"id":"5e769013b5f86ade","repo":"gastownhall/beads","slug":"fork-child-w","errorCode":null,"errorMessage":"fork child: %w","messagePattern":"fork child: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/endpoint.go","lineNumber":338,"sourceCode":"\tcurrentEpoch, err := readStopEpoch(rootDir)\n\tif err != nil {\n\t\treturn Endpoint{}, fmt.Errorf(\"read proxy stop epoch under lock: %w\", err)\n\t}\n\tif currentEpoch != stopEpoch {\n\t\treturn Endpoint{}, fmt.Errorf(\"%w for %s\", errStartInterrupted, rootDir)\n\t}\n\n\tif err := quarantineForSpawn(rootDir, discovery); err != nil {\n\t\treturn Endpoint{}, err\n\t}\n\tif err := cleanupOrphanBackend(rootDir); err != nil {\n\t\treturn Endpoint{}, err\n\t}\n\n\thandedOff = true\n\tchild, err := forkExecChild(rootDir, opts, opts.Port, stopEpoch, lock)\n\tif err != nil {\n\t\treturn Endpoint{}, fmt.Errorf(\"fork child: %w\", err)\n\t}\n\tdefer func() { _ = clearOwnSpawnMarker(rootDir, child.marker) }()\n\tdefer func() {\n\t\tif child.handle != nil {\n\t\t\t_ = child.handle.Close()\n\t\t}\n\t}()\n\n\thard := time.NewTimer(spawnReadyHardTimeout)\n\tdefer hard.Stop()\n\tpoll := time.NewTicker(openPollInterval)\n\tdefer poll.Stop()\n\n\tfor {\n\t\tdiscovered := readAndDial(rootDir)\n\t\tif discovered.status == adoptionAdopted {\n\t\t\tif err := sweepOldQuarantines(rootDir, time.Now()); err != nil {\n\t\t\t\tlog.Printf(\"dbproxy: could not sweep old quarantined records in %s: %v\", rootDir, err)","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/endpoint.go#L320-L356","documentation":"The library failed to fork/exec the proxy child process (forkExecChild). This wraps the OS-level spawn failure — binary missing, exec format or permission problem, or resource limits — after the lock and quarantine steps already succeeded. Everything spawned so far is cleaned up (handoff flag, marker, lock) before returning.","triggerScenarios":"forkExecChild(rootDir, opts, opts.Port, stopEpoch, lock) fails during spawnAndHandoff: opts.DoltBinPath (or the proxy entrypoint binary) does not exist or is not executable, exec fails due to ENOEXEC/EACCES, or fork hits resource limits (ulimit, PID exhaustion).","commonSituations":"bd upgraded/downgraded and the configured DoltBinPath points to an old or removed binary; container images missing the dolt binary; noexec mount on the binary's filesystem; hitting process limits in CI sandboxes.","solutions":["Verify the configured binary path exists and is executable: ls -l $(DoltBinPath) and try running it directly","Check the mount is not noexec (mount output) and fix the binary location","Raise limits (ulimit -u, cgroup pids.max) if fork fails under load","Reinstall/upgrade bd so the bundled paths match the current version"],"exampleFix":"// before\nopts.DoltBinPath = \"/usr/local/bin/dolt\" // binary removed by upgrade\n// error: fork child: fork/exec /usr/local/bin/dolt: no such file or directory\n// after\nif _, err := os.Stat(opts.DoltBinPath); err != nil {\n    opts.DoltBinPath = \"/opt/bd/bin/dolt\" // re-point at the real binary\n}\nep, err := proxy.GetCreateDatabaseProxyServerEndpoint(root, opts)","handlingStrategy":"validation","validationCode":"// Verify the spawn binary before opening\nif opts.DoltBinPath != \"\" {\n    if fi, err := os.Stat(opts.DoltBinPath); err != nil || fi.IsDir() || fi.Mode().Perm()&0o100 == 0 {\n        return fmt.Errorf(\"spawn binary missing or not executable: %s\", opts.DoltBinPath)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Resolve DoltBinPath at startup and fail fast if absent","Keep binaries on exec-permitted mounts (not noexec)","Pin binary versions with bd upgrades; re-check paths after upgrades","Watch ulimit/pids limits in sandboxes"],"tags":["exec","spawn","process","binary"],"backgroundTag":"process-spawn-failure","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}