XTLS/Xray-core · warning
could not get process path for PID :
Error message
could not get process path for PID :
What it means
A best-matching PID was found on macOS, but reading that process's executable path via darwinProcessPath (proc_pidpath) failed. The wrapped error after 'PID <n>:' carries the underlying syscall failure. The match succeeded; only path resolution failed, typically because the process exited or is protected.
Source
Thrown at common/net/find_process_darwin.go:126
bestLevel = matchLevel
ambiguousBest = false
continue
}
if matchLevel == bestLevel {
ambiguousBest = true
}
}
if bestLevel == darwinSocketNoMatch {
return 0, "", "", errors.New("process not found for ", network, " connection from ", srcIP, ":", srcPort, " to ", destIP, ":", destPort)
}
if ambiguousBest {
return 0, "", "", errors.New("ambiguous process match for ", network, " connection from ", srcIP, ":", srcPort, " to ", destIP, ":", destPort)
}
absPath, err := darwinProcessPath(bestPID)
if err != nil {
return 0, "", "", errors.New("could not get process path for PID ", bestPID, ": ", err)
}
absPath = filepath.ToSlash(absPath)
return int(bestPID), filepath.Base(absPath), absPath, nil
}
func darwinProcessSocketMatchLevel(pid int32, network string, srcAddr netip.Addr, srcPort uint16, dstAddr netip.Addr, dstPort uint16, hasDstAddr bool) (darwinSocketMatchLevel, error) {
fds, err := darwinProcessFDs(pid)
if err != nil {
return darwinSocketNoMatch, err
}
bestLevel := darwinSocketNoMatch
info := make([]byte, darwinSocketFDInfoSize)
for fd := 0; fd+darwinProcFDInfoSize <= len(fds); fd += darwinProcFDInfoSize {
fdNumber := int32(darwinReadNativeUint32(fds[fd : fd+4]))
fdType := darwinReadNativeUint32(fds[fd+4 : fd+8])
if fdType != darwinProcFDTypeSocket {View on GitHub (pinned to 7d214f8b09)
Solutions
- Read the wrapped error: ESRCH means the process exited (retry or ignore), EPERM means permission (run elevated or skip)
- Retry the whole FindProcess call once for racy exits
- Fall back to routing without the process path
- For cross-user lookups, run the Xray process with sufficient privileges
Defensive patterns
Strategy: retry
Type guard
func isProcessPathError(err error) bool {
return err != nil && strings.Contains(err.Error(), "could not get process path")
} Try / catch
for attempt := 0; attempt < 2; attempt++ {
pid, name, path, err = net.FindProcess(netw, srcIP, srcPort, dstIP, dstPort)
if err == nil || !isProcessPathError(err) { break }
// matched process likely exited; one retry re-enumerates everything
} Prevention
- Distinguish ESRCH (exited, retry) from EPERM (protected, skip) in the wrapped error
- Keep process rules best-effort with a single retry budget to bound cost
When it happens
Trigger: The matched process exits between the FD scan and the proc_pidpath call (race on short-lived processes); the matched process is a system/sip-protected process where proc_pidpath returns an error for unprivileged callers.
Common situations: Looking up the process for connections owned by short-lived helpers (curl, dig, xargs children) that finish before path resolution; looking up processes owned by other users without elevated privileges.
Related errors
- process not found for connection from ::: to :
- empty process path
- failed to determine if address is local:
- invalid source IP address:
- invalid destination IP address:
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/14b9295278802e06.
Report an issue: GitHub.