gastownhall/beads · warning
finding process %d: %w
Error message
finding process %d: %w
What it means
gracefulStop wraps the error from os.FindProcess(pid) as "finding process %d: %w". os.FindProcess on Unix only fails if the pid is invalid or the OS lookup errors (it does NOT verify the process exists); on Windows it opens a handle and fails if the PID is dead. This library throws it when it cannot obtain a handle to the dolt-server process it is trying to stop gracefully (SIGTERM, then SIGKILL) during reclaimPort or StopWithForce.
Source
Thrown at internal/doltserver/doltserver_unix.go:142
return false
}
// isProcessAlive checks if a process with the given PID is running.
// Uses signal 0 which doesn't send a signal but checks process existence.
func isProcessAlive(pid int) bool {
process, err := os.FindProcess(pid)
if err != nil {
return false
}
return process.Signal(syscall.Signal(0)) == nil
}
// gracefulStop sends SIGTERM, waits for the process to exit, then SIGKILL if needed.
// Used by reclaimPort and StopWithForce where data has already been flushed.
func gracefulStop(pid int, timeout time.Duration) error {
process, err := os.FindProcess(pid)
if err != nil {
return fmt.Errorf("finding process %d: %w", pid, err)
}
if err := process.Signal(syscall.SIGTERM); err != nil {
return fmt.Errorf("sending SIGTERM to PID %d: %w", pid, err)
}
// Poll for exit
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
time.Sleep(500 * time.Millisecond)
if process.Signal(syscall.Signal(0)) != nil {
return nil // exited
}
}
// Still running — force kill
_ = process.Signal(syscall.SIGKILL)
time.Sleep(100 * time.Millisecond)View on GitHub (pinned to 71377f2769)
Solutions
- Check the pid being passed is the valid, current dolt-server PID from server metadata; re-read metadata in case it is stale.
- Treat 'process already done' (os.ErrProcessDone) as success — the goal was a stopped server; retry the port bind instead of failing.
- On Unix, verify liveness with signal 0 (process.Signal(syscall.Signal(0))) before assuming the stop failed.
- Log and continue: if the process is gone, the port is likely free; proceed with startup.
Example fix
// before
process, err := os.FindProcess(pid)
if err != nil {
return fmt.Errorf("finding process %d: %w", pid, err)
}
// after
process, err := os.FindProcess(pid)
if err != nil {
if pid <= 0 {
return fmt.Errorf("finding process %d: %w", pid, err)
}
// already-gone: treat as stopped
return nil
} Defensive patterns
Strategy: try-catch
Validate before calling
if pid <= 0 {
return fmt.Errorf("invalid pid %d; refresh server metadata", pid)
}
if p, err := os.FindProcess(pid); err == nil {
if err := p.Signal(syscall.Signal(0)); err != nil {
// process already gone; no stop needed
}
} Type guard
func pidLooksAlive(pid int) bool {
if pid <= 0 { return false }
p, err := os.FindProcess(pid)
if err != nil { return false }
return p.Signal(syscall.Signal(0)) == nil
} Try / catch
err := gracefulStop(pid, timeout)
if err != nil {
if errors.Is(err, os.ErrProcessDone) {
return nil // already stopped
}
return fmt.Errorf("graceful stop pid %d: %w", pid, err)
} Prevention
- Refresh server metadata before stopping so the PID is current
- Probe liveness with signal 0 before issuing SIGTERM
- Treat 'process not found' as success when the goal is a stopped server
- Run bd as the same user that owns the server process
When it happens
Trigger: Calling gracefulStop (via reclaimPort or StopWithForce) with a pid <= 0 or a stale pid whose process already exited (Windows), or an OS-level failure in process lookup.
Common situations: A dolt server recorded in the metadata file died on its own before bd tried to stop it; a recycled/stale PID in stored server metadata; passing a zero or negative PID from a failed earlier parse.
Related errors
- sending SIGTERM to PID %d: %w
- finding process %d: %w
- procid: process %d does not match token
- procid: terminate process: %w
- procid: process no longer matches token
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c8c81f44a386a7bd.
Report an issue: GitHub.