pranshuparmar/witr · warning
process not found
Error message
process %d not found
What it means
After ps succeeds, ReadProcess expects a non-empty line of output; an empty response means ps accepted the -p filter but printed nothing, i.e. the process does not exist (or is not visible to the current user in some configurations). Distinct from error 23 because ps exited successfully.
Solutions
- Confirm the PID exists with a separate `ps -p <pid>` check before calling.
- Treat it as 'process not found' and handle like the wrapped-error case (error 23).
- Retry once quickly; if it fails again the process is gone.
- If reproducible for a live PID, check that the `ps` in PATH is the system ps (buildEnvForPS minimizes env interference; verify no wrapper shadows it).
Defensive patterns
Strategy: validation
Validate before calling
out, err := exec.Command("ps", "-p", strconv.Itoa(pid)).Output()
if err != nil || len(strings.TrimSpace(string(out))) == 0 {
// process not visible/exited — skip ReadProcess
} Try / catch
proc, err := proc.ReadProcess(pid)
if err != nil {
if strings.Contains(err.Error(), "process "+pidStr+" not found") {
// empty ps output: treat identically to the wrapped-error not-found case
}
} Prevention
- Retry once quickly before declaring the process gone
- Ensure the system ps is used, not a wrapper/alias
- Treat both not-found variants (23 and 24) uniformly in error handling
When it happens
Trigger: ReadProcess called on a PID that ps resolves to zero lines — the process exited in the window between ps's internal lookup and output, or a permissions/visibility edge case where ps exits 0 with no rows.
Common situations: Racing short-lived processes; ps wrappers/aliases in the environment altering behavior; PID reuse checks where the process vanished mid-call.
Related errors
AI-assisted analysis of pranshuparmar/witr@dc4fa1da82 (2026-09-01).
Data as JSON: /api/errors/51bca7739af40bd8.
Report an issue: GitHub.
Appendix: source
Thrown at internal/proc/process_darwin.go:35
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() {
startedAt = time.Now().UTC()
}
state := fields[8]
View on GitHub (pinned to dc4fa1da82)