pranshuparmar/witr · warning

process %d 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.

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)

Solutions

  1. Confirm the PID exists with a separate `ps -p <pid>` check before calling.
  2. Treat it as 'process not found' and handle like the wrapped-error case (error 23).
  3. Retry once quickly; if it fails again the process is gone.
  4. 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

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.