gastownhall/beads · warning
finding process %d: %w
Error message
finding process %d: %w
What it means
The Windows variant of gracefulStop wraps os.FindProcess(pid) failures as "finding process %d: %w". On Windows FindProcess opens a real handle, so it fails immediately when the PID is dead or invalid. Data safety comes from FlushRunningSet in StopWithForce, not from this signal, so the error means bd could not even reach the process to kill it.
Source
Thrown at internal/doltserver/doltserver_windows.go:123
func isProcessAlive(pid int) bool {
h, err := windows.OpenProcess(windows.SYNCHRONIZE, false, uint32(pid))
if err != nil {
return false
}
defer func() { _ = windows.CloseHandle(h) }()
status, err := windows.WaitForSingleObject(h, 0)
return err == nil && status == uint32(windows.WAIT_TIMEOUT)
}
// gracefulStop terminates a process on Windows. Uses TerminateProcess (hard kill)
// directly. Data safety comes from FlushWorkingSet which runs in StopWithForce
// before calling gracefulStop. The Unix SIGTERM is a courtesy; the real protection
// is the flush.
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)
}
_ = process.Kill()
time.Sleep(500 * time.Millisecond)
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Re-read server metadata to confirm the PID is current; delete stale metadata if the server is gone.
- Treat a not-found PID as 'server already stopped' and continue startup — the flush already happened.
- Check the running dolt-server process list (tasklist) to find the real PID if one is truly alive.
- If the port is still occupied by another process, reclaim by port rather than by stored PID.
Defensive patterns
Strategy: fallback
Validate before calling
if pid <= 0 {
// stale metadata; skip stop entirely
return nil
}
// Windows: FindProcess fails for dead PIDs, so probe first
if _, err := os.FindProcess(pid); err != nil {
return nil // already gone
} Type guard
func pidResolvable(pid int) bool {
if pid <= 0 { return false }
_, err := os.FindProcess(pid)
return err == nil
} Try / catch
err := gracefulStop(pid, timeout)
if err != nil {
// FlushWorkingSet already ran; treat as best-effort
log.Printf("could not stop pid %d (may already be dead): %v", pid, err)
return nil
} Prevention
- Delete stale server metadata instead of trusting its PID
- Verify the process exists via tasklist before killing
- Remember Windows FindProcess fails on dead PIDs (unlike Unix)
- Rely on FlushWorkingSet for data safety, not the kill
When it happens
Trigger: StopWithForce on Windows calls gracefulStop with a PID that no longer exists (server already exited), a PID reused by another process that then closed, or pid <= 0 from corrupted server metadata.
Common situations: Stale .dolt/server metadata after a crash or reboot; PID recycling assigning the old number to a short-lived process; bd run under a different user without handle-open rights on the target process.
Related errors
- finding process %d: %w
- sending SIGTERM to PID %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/e9b4dd8523885b9a.
Report an issue: GitHub.