wavetermdev/waveterm · warning · ErrNotFound
procinfo: process not found
Error message
procinfo: process not found
What it means
procinfo.ErrNotFound is returned by GetProcInfo (and its helpers readStat/readUid) when the requested pid does not exist — i.e. /proc/<pid>/stat or /proc/<pid>/status cannot be read because the process is gone or never existed. It is a sentinel error so callers can use errors.Is to distinguish 'no such process' from other I/O failures.
Source
Thrown at pkg/util/procinfo/procinfo.go:9
// Copyright 2026, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package procinfo
import "errors"
// ErrNotFound is returned by GetProcInfo when the requested pid does not exist.
var ErrNotFound = errors.New("procinfo: process not found")
// LinuxStatStatus maps the single-character state from /proc/[pid]/stat to a human-readable name.
var LinuxStatStatus = map[string]string{
"R": "running",
"S": "sleeping",
"D": "disk-wait",
"Z": "zombie",
"T": "stopped",
"t": "tracing-stop",
"W": "paging",
"X": "dead",
"x": "dead",
"K": "wakekill",
"P": "parked",
"I": "idle",
}
// ProcInfo holds per-process information read from the OS.View on GitHub (pinned to a4447c1563)
Solutions
- Use errors.Is(err, procinfo.ErrNotFound) to detect the missing-process case and handle it as an expected outcome.
- Retry once after a short delay if the process was just spawned — it may not have been fully registered yet.
- Verify the pid is still alive (e.g. signal 0 or /proc/<pid> existence) before calling GetProcInfo.
- Check permissions: if /proc/<pid>/stat is unreadable due to ownership, the same sentinel may surface.
Example fix
// before
info, err := procinfo.GetProcInfo(pid)
if err != nil {
return err
}
// after
info, err := procinfo.GetProcInfo(pid)
if errors.Is(err, procinfo.ErrNotFound) {
return nil // process already exited
}
if err != nil {
return err
} Defensive patterns
Strategy: type-guard
Validate before calling
if _, err := os.Stat(fmt.Sprintf("/proc/%d/stat", pid)); os.IsNotExist(err) {
// pid already gone; skip GetProcInfo
} Type guard
func isProcNotFound(err error) bool { return errors.Is(err, procinfo.ErrNotFound) } Try / catch
info, err := procinfo.GetProcInfo(pid)
if errors.Is(err, procinfo.ErrNotFound) {
return nil // expected race: process exited
}
if err != nil {
return err // real I/O or permission failure
} Prevention
- Never assume a pid observed earlier is still alive; /proc entries vanish instantly on exit.
- Always branch on errors.Is(err, procinfo.ErrNotFound) before generic error handling.
- Add a small retry for very recently spawned pids.
- Log the pid with the failure to distinguish races from permission issues.
When it happens
Trigger: Calling procinfo.GetProcInfo(pid) for a pid that has exited, is not owned/readable, or never existed; EnsureInitialData/InitMainServer polling a process that terminated between listing and reading its /proc entries.
Common situations: Race between finding a pid (e.g. from a child process spawn) and querying its info; short-lived worker processes that exit before status is read; querying pids from a stale process list; running in a container where /proc of the host is restricted.
Related errors
- beginning of file
- failed to run app: %w
- failed to setsid: %w
- failed to start remote command: %w
- remote command failed: %w (stderr: %s)
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/3a35bc2e111d8d74.
Report an issue: GitHub.