gastownhall/beads · error
confirm verified pid %d stopped: %w
Error message
confirm verified pid %d stopped: %w
What it means
After killing the verified recorded process, stopAndAcquire polls (waitForRecordedProcessExit) for the process to actually exit within the wait budget (at least 2s, bounded by the 5s deadline). If the process is still alive when the budget expires, this error is thrown so Shutdown doesn't hand back a lock while the old owner may still hold resources.
Source
Thrown at internal/storage/dbproxy/proxy/shutdown.go:273
if _, quarantineErr := quarantineRecord(rootDir, pidName, time.Now()); quarantineErr != nil {
lock.Unlock()
return nil, fmt.Errorf("quarantine dead process record %s: %w", recordPath, quarantineErr)
}
return lock, nil
}
if killErr := handle.Kill(); killErr != nil {
_ = handle.Close()
lock.Unlock()
return nil, fmt.Errorf("kill verified pid %d from %s: %w", pf.Pid, recordPath, killErr)
}
if closeErr := handle.Close(); closeErr != nil {
lock.Unlock()
return nil, fmt.Errorf("close verified process handle for pid %d: %w", pf.Pid, closeErr)
}
waitBudget := max(time.Until(deadline), shutdownPostKillMinimum)
if waitErr := waitForRecordedProcessExit(pf, waitBudget); waitErr != nil {
lock.Unlock()
return nil, fmt.Errorf("confirm verified pid %d stopped: %w", pf.Pid, waitErr)
}
if removeErr := pidfile.Remove(rootDir, pidName); removeErr != nil {
lock.Unlock()
return nil, fmt.Errorf("remove stopped process record %s: %w", recordPath, removeErr)
}
return lock, nil
case !lockfile.IsLocked(err):
return nil, fmt.Errorf("probe %s: %w", lockPath, err)
}
pf, readErr := pidfile.Read(rootDir, pidName)
if readErr != nil {
if isMalformedPIDFileError(readErr) {
return nil, unverifiableProcessError(
"shutdown",
recordPath,
0,View on GitHub (pinned to 71377f2769)
Solutions
- Check the process state with ps -o stat= -p <pid>; 'D' means uninterruptible I/O — fix the underlying storage/mount issue.
- Wait a moment and re-run bd shutdown; the next attempt will see it dead and quarantine/record-remove it.
- If it is a zombie, reap it from the parent process or exit the parent.
- As a last resort, remove the stale pidfile and lock manually and retry.
Example fix
// before $ bd dolt stop // error: confirm verified pid 4321 stopped: process did not exit within 2s // after $ ps -o stat= -p 4321 # inspect state; if 'Z', reap parent; if 'D', fix I/O $ bd dolt stop # retry
Defensive patterns
Strategy: retry
Validate before calling
pid=$(awk 'NR==1{print $1}' .beads/dolt.pid 2>/dev/null); [ -n "$pid" ] && [ "$(ps -o stat= -p $pid 2>/dev/null | tr -d ' ')" = "D" ] && echo 'process in uninterruptible I/O; fix storage first' Try / catch
if err := proxy.Shutdown(rootDir); err != nil && strings.Contains(err.Error(), "confirm verified pid") {
// check ps state, then retry after a short delay
time.Sleep(2 * time.Second)
err = proxy.Shutdown(rootDir)
} Prevention
- Avoid hanging NFS/network mounts for workspace storage.
- Reap children promptly in wrapper scripts around bd.
- Retry shutdown rather than force-removing files immediately.
When it happens
Trigger: A verified proxy/backend process was SIGKILLed but remained observable (e.g. uninterruptible D state on Linux, slow kernel cleanup, zombie reaped late) past max(time.Until(deadline), 2s).
Common situations: Process stuck in uninterruptible I/O (D state) on a hung filesystem/NFS mount; extremely loaded machine delaying process teardown; zombie process not yet reaped by its parent.
Related errors
- ErrUnverifiableProcess
- procid: process %d still matches token after fatal signal an
- timeout (%s) waiting for spawn marker %s; wait for the in-pr
- kill verified pid %d from %s: %w
- close verified process handle for pid %d: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/25ac7652c176d442.
Report an issue: GitHub.