{"record":{"id":"2511127e7c84e3b7","repo":"gastownhall/beads","slug":"proxy-forcestopunverified-open-pid-d-w","errorCode":null,"errorMessage":"proxy.ForceStopUnverified: open pid %d: %w","messagePattern":"proxy\\.ForceStopUnverified: open pid (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/force_stop.go","lineNumber":198,"sourceCode":"\t}\n\tif record.RootID == rootID {\n\t\treturn errors.New(\n\t\t\t\"proxy.ForceStopUnverified: record has a verifiable v2 workspace identity; use proxy.Shutdown\",\n\t\t)\n\t}\n\treturn nil\n}\n\nfunc inspectAndStopUnverifiedPID(rootDir string, pid int, deadline time.Time, report *ForceStopReport) error {\n\tif pid <= 0 {\n\t\treturn fmt.Errorf(\"proxy.ForceStopUnverified: record %s has invalid pid %d\", report.RecordPath, pid)\n\t}\n\t// One stable handle covers inspection and signaling, so the PID cannot be\n\t// recycled between the executable check and the kill on platforms with a\n\t// pinning primitive (Linux pidfd, Windows process handle).\n\tproc, gone, err := openUnverifiedProcess(pid)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"proxy.ForceStopUnverified: open pid %d: %w\", pid, err)\n\t}\n\tif gone {\n\t\treport.ProcessWasGone = true\n\t\treturn nil\n\t}\n\tdefer proc.close()\n\n\texecutable, gone, err := proc.executableBasename()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"proxy.ForceStopUnverified: inspect executable for pid %d: %w\", pid, err)\n\t}\n\tif gone {\n\t\treport.ProcessWasGone = true\n\t\treturn nil\n\t}\n\texecutable = normalizeForceStopExecutable(executable)\n\treport.Executable = executable\n\tif executable != \"bd\" && executable != \"dolt\" {","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/force_stop.go#L180-L216","documentation":"This error wraps a failure to open a handle to the unverified process identified by the record PID, so it can be inspected and signaled atomically. The library throws it when openUnverifiedProcess fails (e.g. opening /proc/<pid>, or OpenProcess on Windows fails for reasons other than the process being gone), because without a stable handle the executable check and kill could race with PID reuse.","triggerScenarios":"Calling ForceStopUnverified when openUnverifiedProcess(pid) returns an error (not the 'gone' path) — e.g. insufficient privileges to inspect a foreign-owned PID, an OS API failure, or a PID that vanished between existence check and handle creation in a race window.","commonSituations":"Force-stopping a proxy owned by another user/container UID, restricted hardened environments (seccomp/AppArmor blocking pidfd_open or /proc access), or extremely short-lived processes exiting during the open call.","solutions":["Re-run the command — if the process exited in a race, the next attempt will take the 'gone' path","Run with sufficient privileges (or as the same user who owns the proxy process) so the OS permits opening the target","Check the wrapped cause (%w): EPERM/EACCES means permissions; ENOENT usually means the process exited and a retry suffices","As root (or the owning user), remove the stale record manually after confirming the process is gone"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"func canOpen(pid int) error {\n    return unix.Faccessat(unix.AT_FDCWD, fmt.Sprintf(\"/proc/%d\", pid), unix.R_OK, 0)\n}","typeGuard":null,"tryCatchPattern":"report, err := proxy.ForceStopUnverified(rootDir)\nif err != nil && strings.Contains(err.Error(), \"open pid \") {\n    var perr syscall.Errno\n    if errors.As(err, &perr) && (errors.Is(perr, syscall.ENOENT) || errors.Is(perr, syscall.ESRCH)) {\n        // process likely exited in a race; retry once\n        report, err = proxy.ForceStopUnverified(rootDir)\n    }\n}","preventionTips":["Run force-stop as the same user that owns the proxy process","Avoid hardened seccomp/AppArmor profiles that block pidfd_open or /proc reads","Handle EPERM by elevating privileges only after confirming the target PID","Treat ENOENT/ESRCH as 'process gone' and retry rather than escalating"],"tags":["process","permissions","pidfd","force-stop","pid-reuse"],"backgroundTag":"process-open-permission-denied","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}