gastownhall/beads · error
proxy.ForceStopUnverified: record %s has invalid pid %d
Error message
proxy.ForceStopUnverified: record %s has invalid pid %d
What it means
inspectAndStopUnverifiedPID validates the PID from the force-stop record and rejects non-positive values because they can never name a real process. The library throws this when the record contains pid <= 0, indicating a corrupt or malformed record rather than a stoppable target.
Source
Thrown at internal/storage/dbproxy/proxy/force_stop.go:191
return nil
}
rootID, err := identity.RootID(rootDir)
if err != nil {
// Failing open here would route a possibly-verifiable record into the
// destructive force path; surface the identity failure instead.
return fmt.Errorf("proxy.ForceStopUnverified: resolve workspace identity: %w", err)
}
if record.RootID == rootID {
return errors.New(
"proxy.ForceStopUnverified: record has a verifiable v2 workspace identity; use proxy.Shutdown",
)
}
return nil
}
func inspectAndStopUnverifiedPID(rootDir string, pid int, deadline time.Time, report *ForceStopReport) error {
if pid <= 0 {
return fmt.Errorf("proxy.ForceStopUnverified: record %s has invalid pid %d", report.RecordPath, pid)
}
// One stable handle covers inspection and signaling, so the PID cannot be
// recycled between the executable check and the kill on platforms with a
// pinning primitive (Linux pidfd, Windows process handle).
proc, gone, err := openUnverifiedProcess(pid)
if err != nil {
return fmt.Errorf("proxy.ForceStopUnverified: open pid %d: %w", pid, err)
}
if gone {
report.ProcessWasGone = true
return nil
}
defer proc.close()
executable, gone, err := proc.executableBasename()
if err != nil {
return fmt.Errorf("proxy.ForceStopUnverified: inspect executable for pid %d: %w", pid, err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Delete the malformed record file (<rootDir> PID/lock record path) and retry, since it names no real process
- Verify with ps that no live proxy exists for the workspace; if none, the record is safely removable
- Fix whatever wrote the placeholder PID (check for prior crash during record write)
- Re-run the normal bd command to regenerate a valid record
Example fix
// before
pid := parsePid(data) // may yield 0
_ = inspectAndStopUnverifiedPID(rootDir, pid, deadline, report)
// after
pid := parsePid(data)
if pid <= 0 {
_ = os.Remove(report.RecordPath)
return nil
}
_ = inspectAndStopUnverifiedPID(rootDir, pid, deadline, report) Defensive patterns
Strategy: validation
Validate before calling
func recordPidValid(path string) bool {
data, err := os.ReadFile(path)
if err != nil {
return false
}
pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
return err == nil && pid > 0
} Type guard
func isPositivePid(n int) bool { return n > 0 } Try / catch
report, err := proxy.ForceStopUnverified(rootDir)
if err != nil && strings.Contains(err.Error(), "has invalid pid") {
// Record names no real process; remove it and retry
if rec := report.RecordPath; rec != "" {
_ = os.Remove(rec)
report, err = proxy.ForceStopUnverified(rootDir)
}
} Prevention
- Treat pid<=0 records as stale and removable after confirming no live proxy
- Avoid partial writes to PID files (write temp + rename)
- Add checks that reject placeholder PIDs when producing records
- Re-run a normal bd command to regenerate valid records
When it happens
Trigger: Calling ForceStopUnverified on a record whose decoded pid is 0 or negative — e.g. a zero-initialized or partially written PID file that still parsed.
Common situations: A PID file truncated to a bare '0' or '-1' after a crash, manual editing, or a tool writing placeholder values.
Related errors
- proxy.ForceStopUnverified: read %s: %w
- pidfile: invalid port
- record has no valid pid
- proxy.ForceStopUnverified: inspect executable for pid %d: %w
- proxy.ForceStopUnverified: refusing to signal pid %d from %s
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6250369c7cca675b.
Report an issue: GitHub.