gastownhall/beads · error
proxy.ForceStopUnverified: signal pid %d: %w
Error message
proxy.ForceStopUnverified: signal pid %d: %w
What it means
All safety checks passed (executable is bd/dolt, command line scoped to this workspace) but the actual signal delivery to the PID failed. This wraps the underlying OS error from proc.kill() — typically EPERM (insufficient permission), ESRCH (process vanished between check and signal), or platform signal API failure. No signal was confirmed delivered.
Source
Thrown at internal/storage/dbproxy/proxy/force_stop.go:257
if gone {
report.ProcessWasGone = true
return nil
}
if !scoped {
return fmt.Errorf(
"proxy.ForceStopUnverified: refusing to signal pid %d from %s: its command line does not reference workspace %s, so it may be an unrelated %s process; stop it manually if it is yours, then quarantine the record by renaming %s to %s.stale-<unix-timestamp> before retrying",
pid,
report.RecordPath,
rootDir,
executable,
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)
}View on GitHub (pinned to 71377f2769)
Solutions
- Re-run the force-stop; if the process died in the race window, the next attempt reports ProcessWasGone and succeeds
- Check process ownership (ps -o user= -p <pid>); run force-stop as the same user or with appropriate privileges (sudo / inside the container)
- If the process is gone but the record remains, quarantine it: rename <record> to <record>.stale-<unix-timestamp> and retry
- Inspect the wrapped cause (%w) for EPERM vs ESRCH to decide between a permissions fix and a stale-record cleanup
Example fix
// before err := proxy.ForceStopUnverified(ctx, rootDir, "bd", deadline) // EPERM // after: run with matching privileges or via sudo // sudo -E bd daemon --force-stop // or in CI: docker exec <container> bd daemon --force-stop
Defensive patterns
Strategy: retry
Validate before calling
// ensure same-user ownership of the target before signaling
pid := readPidFromRecord(recordPath)
si, err := os.Stat(fmt.Sprintf("/proc/%d", pid))
if err == nil {
st := si.Sys().(*syscall.Stat_t)
if int(st.Uid) != os.Getuid() {
// will EPERM: escalate (sudo/container exec) or abandon before calling
}
} Type guard
func isSignalErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "signal pid ")
} Try / catch
err := proxy.ForceStopUnverified(ctx, rootDir, pidName, deadline)
if isSignalErr(err) {
if errors.Is(err, os.ErrPermission) {
return fmt.Errorf("re-run with privileges of the daemon's owner (sudo or container exec)")
}
// ESRCH-style race: one retry resolves as ProcessWasGone
report, err = proxy.ForceStopUnverified(ctx, rootDir, pidName, deadline)
if err != nil { return err }
} Prevention
- Run bd client commands as the same user that started the daemon
- In containers, exec the force-stop inside the daemon's container rather than from the host
- Retry once on transient signal failures — exit races resolve as ProcessWasGone
- Keep the wrapped cause (errors.Unwrap) and branch on EPERM vs ESRCH for the right remedy
When it happens
Trigger: proxy.ForceStopUnverified calling proc.kill() when the process is owned by another user (EPERM), exited in the microseconds between inspection and kill (ESRCH), or the platform signaling primitive (pidfd_send_signal, Windows TerminateProcess) returns an error.
Common situations: bd/dolt daemon started via sudo or in a container owned by root while force-stop runs as a normal user; extremely short-lived processes racing exit; restricted seccomp policies blocking signal syscalls; PID handed to a child re-parented to another user.
Related errors
- procid: signal %d: %w
- kill verified orphan backend pid %d from %s: %w
- proxy.ForceStopUnverified: publish stop epoch: %w
- proxy.ForceStopUnverified: probe %s: %w
- proxy.ForceStopUnverified: open pid %d: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/b51272e4649afc54.
Report an issue: GitHub.