gastownhall/beads · error
kill verified pid %d from %s: %w
Error message
kill verified pid %d from %s: %w
What it means
During proxy.Shutdown, stopAndAcquire verified a recorded PID legitimately belongs to this workspace's proxy/backend and tried to kill it, but the OS kill call (handle.Kill()) failed. The error wraps the underlying syscall error (e.g. permission denied, process gone). Shutdown refuses to continue rather than leaving the lock in an unknown state.
Source
Thrown at internal/storage/dbproxy/proxy/shutdown.go:264
return nil, unverifiableProcessError(
"shutdown",
recordPath,
pf.Pid,
openErr,
unverifiableProcessChecks{},
)
}
if dead {
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)View on GitHub (pinned to 71377f2769)
Solutions
- Run the shutdown command as the same user that started the daemon (check with ps -o user= -p <pid>).
- If the process already exited, delete the stale pidfile and lock, then retry bd shutdown.
- Check the wrapped %w error: EPERM means permissions, ESRCH means already gone.
- Kill the process manually (kill <pid>) and remove the pidfile, then retry.
Example fix
// before err := proxy.Shutdown(rootDir) // fails: kill verified pid 4321 ...: operation not permitted // after // start daemon and shutdown as the same user $ bd dolt start # as user 'alice' $ bd dolt stop # also as user 'alice'
Defensive patterns
Strategy: try-catch
Validate before calling
pid=$(cat .beads/dolt.pid | head -1); [ "$(ps -o user= -p ${pid#*:} 2>/dev/null | tr -d ' ')" = "$(whoami)" ] && echo ok || echo 'pid owned by another user; run shutdown as that user' Try / catch
if err := proxy.Shutdown(rootDir); err != nil {
var uerr *UnverifiableProcessError
if errors.As(err, &uerr) { /* handle legacy/unverifiable path */ }
if strings.Contains(err.Error(), "kill verified pid") {
// advise same-user restart or manual kill + pidfile removal
}
} Prevention
- Always start and stop the daemon as the same OS user.
- Avoid sudo for bd daemon commands.
- Don't run bd on NFS or inside mismatched container namespaces.
- Clean stale pidfiles after abnormal exits.
When it happens
Trigger: bd Shutdown finds a live, verified pid in the pidfile and handle.Kill() returns an error — typically EPERM because the recorded process runs as a different user, or the process exited between open and kill.
Common situations: The daemon was started under sudo or another account while shutdown runs as the current user; a container/namespace boundary makes the PID invisible or unkillable; a race where the process exits just before the kill.
Related errors
- ErrUnverifiableProcess
- finding process %d: %w
- sending SIGTERM to PID %d: %w
- procid: terminate process: %w
- procid: get process exit code: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/470d856ab590a015.
Report an issue: GitHub.