v2rayA/v2rayA · error
findProcessID: %w
Error message
findProcessID: %w
What it means
findProcessID wraps any failure of os.ReadDir("/proc") as 'findProcessID: %w', preserving the underlying permission/OS error. Unlike ProcOpenFailedErr (used by FillProcesses), this path keeps the cause, so unwrapping reveals whether it was a permission denial, missing /proc, or another filesystem error.
Source
Thrown at service/common/netTools/netstat/netstat_unix.go:173
PPID: ppid,
Name: pn,
}
return s.Proc, nil
}
}
return nil, SocketFreedErr
}
/*
没有做缓存,每次调用都会扫描,消耗资源
*/
var ErrorNotFound = fmt.Errorf("process not found")
func findProcessID(pname string) (pids []string, err error) {
f, err := os.ReadDir(pathProc)
if err != nil {
err = fmt.Errorf("findProcessID: %w", err)
return
}
loop1:
for _, fi := range f {
if !fi.IsDir() {
continue
}
fn := fi.Name()
for _, t := range fn {
if t > '9' || t < '0' {
continue loop1
}
}
if pn, _ := getProcessInfo(fn); pn == pname {
pids = append(pids, fn)
}
}
if len(pids) > 0 {View on GitHub (pinned to 71e5442fc5)
Solutions
- Unwrap the error (errors.Unwrap / %w chain) to see the real *fs.PathError and its errno (EACCES, ENOENT).
- Run the lookup with sufficient privileges or relax /proc permissions (hidepid) so the service user can list /proc.
- Ensure /proc is mounted in the runtime environment (containers) before calling the netstat functions.
- Guard the environment first: os.Stat("/proc") and os.ReadDir("/proc") sanity check, or build-tag platform-specific code properly.
Example fix
// before
ok, err := netstat.IsProcessListenPort("nginx", 80)
if err != nil { log.Fatal(err) } // opaque without unwrap
// after
ok, err := netstat.IsProcessListenPort("nginx", 80)
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) { log.Fatalf("proc access %s: %v", pe.Path, pe.Err) }
} Defensive patterns
Strategy: validation
Validate before calling
func procReadable() error {
if _, err := os.ReadDir("/proc"); err != nil {
return fmt.Errorf("/proc not listable: %w", err)
}
return nil
} Type guard
func canEnumerateProc() bool {
_, err := os.ReadDir("/proc")
return err == nil
} Try / catch
pids, err := findProcessID("myapp") // via IsProcessListenPort
if err != nil {
if errors.Is(err, netstat.ErrorNotFound) { return false, nil }
var pe *fs.PathError
if errors.As(err, &pe) {
log.Fatalf("proc access denied at %s: %v", pe.Path, pe.Err)
}
return err
} Prevention
- Unwrap the error: unlike ProcOpenFailedErr, this path preserves the real OS error via %w.
- Check /proc permissions (hidepid=2 blocks non-root listing of other users' processes).
- Verify the runtime platform actually has procfs — this file is linux-tagged but errors cryptically elsewhere.
- Run pre-flight os.ReadDir("/proc") checks in health/setup code.
When it happens
Trigger: IsProcessListenPort -> findProcessID on a host where /proc cannot be enumerated: hidepid=2 mount, read-protected /proc, chroot without procfs, or non-procfs Unix despite the linux build tag.
Common situations: Hardened servers with /proc restricted to root while the service runs unprivileged; minimal containers without procfs mounted; running the binary on macOS/BSD (file is guarded by // +build linux plan9 freebsd solaris) where /proc doesn't exist.
Related errors
- cannot open the directory /proc
- getProcessSocketSet: %w
- ExecCommands: %v %v: %w
- parseAddr: Bad formatted string
- parseAddr: %w
AI-assisted analysis of v2rayA/v2rayA@71e5442fc5 (2026-09-05).
Data as JSON: /api/errors/8a4c76e55b7d5083.
Report an issue: GitHub.