gastownhall/beads · error
proxy.ForceStopUnverified: confirm pid %d exit: %w
Error message
proxy.ForceStopUnverified: confirm pid %d exit: %w
What it means
This error is returned by inspectAndStopUnverifiedPID inside ForceStopUnverified (`bd dolt stop --force`) after SIGKILL has already been sent to the recorded unverified process, when polling the process handle to confirm it actually exited fails. It is not a timeout — the exit-check API itself returned an error (e.g. the process handle became unusable or the OS query failed). The wrapped cause (%w) carries the underlying OS-level reason.
Source
Thrown at internal/storage/dbproxy/proxy/force_stop.go:268
report.RecordPath,
report.RecordPath,
)
}
gone, err = proc.kill()
if err != nil {
return fmt.Errorf("proxy.ForceStopUnverified: signal pid %d: %w", pid, err)
}
if gone {
report.ProcessWasGone = true
return nil
}
report.SignalSent = true
for {
exited, err := proc.exited()
if err != nil {
return fmt.Errorf("proxy.ForceStopUnverified: confirm pid %d exit: %w", pid, err)
}
if exited {
return nil
}
if time.Now().After(deadline) {
return fmt.Errorf("proxy.ForceStopUnverified: timeout waiting for pid %d to exit", pid)
}
time.Sleep(shutdownConfirmPoll)
}
}
func normalizeForceStopExecutable(name string) string {
name = strings.TrimSpace(filepath.Base(name))
name = strings.TrimSuffix(name, " (deleted)")
name = strings.TrimSuffix(strings.ToLower(name), ".exe")
return name
}
View on GitHub (pinned to 71377f2769)
Solutions
- Re-run `bd dolt stop --force`; the recorded process is usually gone by then and the next run takes the ProcessWasGone path
- Check the wrapped cause (%w) to identify the OS-level failure (e.g. /proc read permission in containers) and fix that environment issue
- Verify the process state manually (ps -p <pid>) and, if it is a zombie, reap its parent or wait for init to reap it before retrying
- If the process is confirmed dead but the record remains, rename proxy.pid to proxy.pid.stale-<unix-timestamp> to quarantine it manually
Defensive patterns
Strategy: retry
Validate before calling
// Confirm the PID is gone before/instead of relying on one force-stop run: alive, err := syscall.Kill(pid, 0) processGone := err == syscall.ESRCH
Try / catch
report, err := proxy.ForceStopUnverified(rootDir)
if err != nil && strings.Contains(err.Error(), "confirm pid") {
// Signal was sent; wait and retry once — the process is likely gone now
time.Sleep(2 * time.Second)
report, err = proxy.ForceStopUnverified(rootDir)
} Prevention
- Use the default timeout rather than an aggressive custom one so polling has room to complete
- Run force-stop in normal (not containerized/restricted /proc) environments where process status reads are reliable
- Check report.SignalSent on partial failure to know the kill already happened before retrying
- Treat any force-stop error as recoverable-by-retry: the second run re-inspects and takes the already-gone fast path
When it happens
Trigger: Call ForceStopUnverified (or `bd dolt stop --force`) on a legacy pre-v2 proxy.pid or proxy-child.pid record whose PID is live, passes the bd/dolt executable and workspace-scope checks, gets signaled, and then proc.exited() fails on a subsequent poll iteration — i.e. the error occurs only after report.SignalSent was set to true.
Common situations: Zombie/defunct processes whose wait status cannot be read; platform handle issues where the pidfd/process handle becomes invalid mid-poll; containerized or restricted /proc environments where process status reads fail intermittently; extremely long-lived polling loops racing with system-level process cleanup.
Related errors
- proxy.ForceStopUnverified: timeout waiting for pid %d to exi
- proxy.ForceStopUnverified: re-read %s: %w
- record has no valid pid
- proxy.ForceStopUnverified: record has a verifiable v2 worksp
- read backend record %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/47b5d964479b83f5.
Report an issue: GitHub.