pranshuparmar/witr · error

invalid pid %d

Error message

invalid pid %d

What it means

On FreeBSD, ReadProcess validates the PID before invoking ps: pid <= 0 is rejected because `ps -p 0` on FreeBSD returns the kernel swapper, which is not a real userland target, matching the guard on other platforms. It is input validation, not a runtime failure.

Source

Thrown at internal/proc/process_freebsd.go:21

package proc

import (
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/pranshuparmar/witr/pkg/model"
)

func ReadProcess(pid int) (model.Process, error) {
	// Reject PID 0 (and negatives): on FreeBSD `ps -p 0` returns the kernel
	// swapper, which is not a real userland target. Matches the other platforms.
	if pid <= 0 {
		return model.Process{}, fmt.Errorf("invalid pid %d", pid)
	}
	pidStr := strconv.Itoa(pid)

	// Format: pid(0) ppid(1) uid(2) jid(3) state(4) pcpu(5) rss(6) lstart(7-11) args(12+)
	// comm is excluded because it can contain spaces, which breaks strings.Fields parsing.
	// The display name is derived from args instead.
	cmd := exec.Command("ps", "-p", pidStr,
		"-o", "pid=", "-o", "ppid=", "-o", "uid=", "-o", "jid=",
		"-o", "state=", "-o", "pcpu=", "-o", "rss=",
		"-o", "lstart=", "-o", "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 == "" {

View on GitHub (pinned to dc4fa1da82)

Solutions

  1. Fix the caller that produced 0/negative PID.
  2. Skip the call when pid <= 0 and treat it as 'unknown process'.
  3. Validate PID > 0 before calling witr APIs.

Example fix

// before
proc, err := proc.ReadProcess(pid) // pid == 0
// after
if pid > 0 {
    proc, err = proc.ReadProcess(pid)
}
Defensive patterns

Strategy: validation

Validate before calling

if pid <= 0 {
    return fmt.Errorf("cannot read process: pid %d is invalid", pid)
}

Try / catch

proc, err := proc.ReadProcess(pid)
if err != nil {
    if strings.Contains(err.Error(), "invalid pid") {
        // input bug: do not retry; fix the PID source
    }
}

Prevention

When it happens

Trigger: Calling ReadProcess (directly or via pidIdentityChanged) with pid <= 0 — typically an uninitialized/zero PID or a sentinel meaning 'no parent found'.

Common situations: Passing 0 for a not-yet-discovered parent PID; zero-valued struct fields flowing into the lookup.

Related errors


AI-assisted analysis of pranshuparmar/witr@dc4fa1da82 (2026-09-01). Data as JSON: /api/errors/ad0b5ca94e327727. Report an issue: GitHub.