gastownhall/beads · error
open process %d: %w
Error message
open process %d: %w
What it means
On Windows, openUnverifiedProcess opens a handle to the PID via OpenProcess to inspect it before any kill. ERROR_INVALID_PARAMETER is treated as 'process gone'; any other OpenProcess failure is wrapped in this error, aborting the force-stop so the proxy never acts on an unverified PID.
Source
Thrown at internal/storage/dbproxy/proxy/unverified_process_windows.go:38
// from recycling the PID underneath us.
type unverifiedProcess struct {
pid int
handle windows.Handle
}
// openUnverifiedProcess opens a stable handle for pid. gone reports a PID
// that no longer exists or has already terminated.
func openUnverifiedProcess(pid int) (proc *unverifiedProcess, gone bool, err error) {
handle, err := windows.OpenProcess(
windows.PROCESS_QUERY_LIMITED_INFORMATION|windows.PROCESS_TERMINATE,
false,
uint32(pid),
)
if err != nil {
if errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return nil, true, nil
}
return nil, false, fmt.Errorf("open process %d: %w", pid, err)
}
exited, err := handleExited(handle)
if err != nil {
_ = windows.CloseHandle(handle)
return nil, false, err
}
if exited {
_ = windows.CloseHandle(handle)
return nil, true, nil
}
return &unverifiedProcess{pid: pid, handle: handle}, false, nil
}
func (p *unverifiedProcess) executableBasename() (basename string, gone bool, err error) {
buffer := make([]uint16, 32768)
size := uint32(len(buffer))
if err := windows.QueryFullProcessImageName(p.handle, 0, &buffer[0], &size); err != nil {
return "", false, fmt.Errorf("query image name for pid %d: %w", p.pid, err)View on GitHub (pinned to 71377f2769)
Solutions
- Run the stop command from an elevated (Administrator) terminal after confirming the PID's identity in Task Manager or `tasklist /FI "PID eq <pid>"`.
- If the PID was recycled to an unrelated process, do not kill it — delete the stale pidfile and restart.
- Check antivirus/EDR policies that block OpenProcess and add an exclusion for bd.
- Reboot or log off stale sessions to clear recycled-PID conflicts, then retry.
Example fix
// before: access denied opening elevated daemon's PID # run non-elevated bd ... // after: elevated terminal Start-Process -Verb RunAs bd ... # or taskkill /PID <pid> /F after verifying
Defensive patterns
Strategy: try-catch
Validate before calling
out, err := exec.Command("tasklist", "/FI", fmt.Sprintf("PID eq %d", pid), "/FO", "CSV", "/NH").Output()
if err == nil && !strings.Contains(string(out), expectedImageName) {
// PID recycled to an unrelated process: do not open/kill
} Try / catch
proc, gone, err := openUnverifiedProcess(pid)
if err != nil {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
// needs elevation or PID owned by another user: verify first
}
return err
} Prevention
- Stop daemons from the same user (and elevation level) that started them.
- Verify PID identity with tasklist before escalating privileges.
- Add antivirus/EDR exclusions for bd so OpenProcess is not blocked.
- Delete stale pidfiles after crashes or reboots to avoid recycled-PID conflicts.
When it happens
Trigger: openUnverifiedProcess calls windows.OpenProcess and receives an error other than ERROR_INVALID_PARAMETER — most commonly ERROR_ACCESS_DENIED (process owned by another user/service, e.g. a recycled PID now owned by SYSTEM).
Common situations: The recorded daemon PID was recycled by a Windows service or another user's process (access denied); running without elevation when the daemon ran elevated; antivirus/EDR blocking handle opens.
Related errors
- read cmdline for pid %d: %w
- dolt path is not executable
- reading another process's command line is not supported on w
- failed to create backup directory: %w
- failed to create temp file: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/297ed8069a004739.
Report an issue: GitHub.