pranshuparmar/witr · warning
process %d not found: %w
Error message
process %d not found: %w
What it means
ReadProcess on macOS runs `ps -p <pid> ...`; when ps exits non-zero (which happens when the PID does not exist) this error wraps the underlying exec error. It is the primary 'process is gone' signal on darwin.
Source
Thrown at internal/proc/process_darwin.go:30
"time"
"github.com/pranshuparmar/witr/pkg/model"
)
func ReadProcess(pid int) (model.Process, error) {
if pid <= 0 {
return model.Process{}, fmt.Errorf("invalid pid %d", pid)
}
pidStr := strconv.Itoa(pid)
// Format: pid(0) ppid(1) uid(2) lstart(3-7) state(8) pcpu(9) rss(10) args(11+)
// ucomm is excluded because it can contain spaces (e.g. "Microsoft Teams"),
// which breaks strings.Fields parsing. The display name is derived from args instead.
cmd := exec.Command("ps", "-p", pidStr, "-o", "pid=,ppid=,uid=,lstart=,state=,pcpu=,rss=,args=")
cmd.Env = buildEnvForPS()
out, err := cmd.Output()
if err != nil {
return model.Process{}, fmt.Errorf("process %d not found: %w", pid, err)
}
line := strings.TrimSpace(string(out))
if line == "" {
return model.Process{}, fmt.Errorf("process %d not found", pid)
}
fields := strings.Fields(line)
if len(fields) < 11 {
return model.Process{}, fmt.Errorf("unexpected ps output format for pid %d", pid)
}
ppid, _ := strconv.Atoi(fields[1])
uid, _ := strconv.Atoi(fields[2])
lstartStr := strings.Join(fields[3:8], " ")
startedAt, _ := time.Parse("Mon Jan 2 15:04:05 2006", lstartStr)
if startedAt.IsZero() {View on GitHub (pinned to dc4fa1da82)
Solutions
- Re-check that the PID exists (`ps -p <pid>`) before retrying; if it exited, the process is gone.
- Retry promptly after obtaining the PID to narrow the exit race.
- Inspect the wrapped error (%w): 'No such process' means exit; 'executable file not found' means ps is missing in the environment.
- Fall back to the platform snapshot or read /proc-like sources if available; or inspect the parent instead.
Defensive patterns
Strategy: try-catch
Validate before calling
// macOS: check existence before ReadProcess
if out, err := exec.Command("ps", "-p", strconv.Itoa(pid), "-o", "pid=").Output(); err != nil || len(strings.TrimSpace(string(out))) == 0 {
return fmt.Errorf("pid %d not running", pid)
} Try / catch
proc, err := proc.ReadProcess(pid)
if err != nil {
if strings.Contains(err.Error(), "not found") {
// process exited between discovery and read: handle as 'gone'
} else {
// inspect wrapped error for environment issues (ps missing)
}
} Prevention
- Minimize delay between obtaining the PID and reading it
- Unwrap the error to distinguish process-exit from ps-availability problems
- Have a fallback path (snapshot/parent inspection) for exited targets
When it happens
Trigger: ReadProcess called with a PID that has already terminated (ps exit status 1); also ps failures such as the binary being unavailable or exec permission issues, which surface wrapped in the same message.
Common situations: Inspecting a process that exited between discovery and the ReadProcess call; watching a parent that reaped and exited a child; running inside restricted containers where ps is missing.
Related errors
- process %d not found
- process %d not found: %w
- process %d not found
- listfds returned partial record
- launchctl blame failed: %w
AI-assisted analysis of pranshuparmar/witr@dc4fa1da82 (2026-09-01).
Data as JSON: /api/errors/3db9a1b2a605bdc5.
Report an issue: GitHub.