{"record":{"id":"bd59e7858c39f770","repo":"XTLS/Xray-core","slug":"could-not-find-pid-for-inode","errorCode":null,"errorMessage":"could not find PID for inode : ","messagePattern":"could not find PID for inode : ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"common/net/find_process_linux.go","lineNumber":63,"sourceCode":"\t\tpanic(\"Unsupported network type for process lookup.\")\n\t}\n\n\ttargetHexAddr, err := formatLittleEndianString(net.ParseIP(srcIP), Port(srcPort))\n\tif err != nil {\n\t\treturn 0, \"\", \"\", errors.New(\"failed to format address: \", err)\n\t}\n\n\tinode, err := findInodeInFile(procFile, targetHexAddr)\n\tif err != nil {\n\t\treturn 0, \"\", \"\", errors.New(\"could not search in \", procFile).Base(err)\n\t}\n\tif inode == \"\" {\n\t\treturn 0, \"\", \"\", errors.New(\"connection for \", srcIP, \":\", srcPort, \" not found in \", procFile)\n\t}\n\n\tpidStr, err := findPidByInode(inode)\n\tif err != nil {\n\t\treturn 0, \"\", \"\", errors.New(\"could not find PID for inode \", inode, \": \", err)\n\t}\n\tif pidStr == \"\" {\n\t\treturn 0, \"\", \"\", errors.New(\"no process found for inode \", inode)\n\t}\n\n\tabsPath, err := getAbsPath(pidStr)\n\tif err != nil {\n\t\treturn 0, \"\", \"\", errors.New(\"could not get process name for PID \", pidStr, \":\", err)\n\t}\n\n\tnameSplit := strings.Split(absPath, \"/\")\n\tprocName := nameSplit[len(nameSplit)-1]\n\n\tpid, err := strconv.Atoi(pidStr)\n\tif err != nil {\n\t\treturn 0, \"\", \"\", errors.New(\"failed to parse PID: \", err)\n\t}\n","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/common/net/find_process_linux.go#L45-L81","documentation":"After finding the socket's inode, FindProcess scans /proc/<pid>/fd/* across all processes to find who owns it; that scan itself returned an error (chained after 'inode <n>:'). Typical wrapped causes are EACCES reading another user's /proc/<pid>/fd, or a directory vanishing mid-scan.","triggerScenarios":"The socket belongs to a process of a different user and the caller lacks permission (unprivileged daemon reading root's FD table); a process exits while findPidByInode is iterating /proc.","commonSituations":"Running Xray as an unprivileged user with process-based routing for all system traffic; hidepid mount option hiding other users' processes entirely.","solutions":["Read the chained error: EACCES/ENOENT mid-scan are mostly benign — re-check if a strict error policy turned them fatal","Run the lookup with sufficient privileges (CAP_SYS_PTRACE or root) when cross-user matching is required","Remove hidepid from the /proc mount or add the caller to a trusted group","Fall back to non-process routing on failure"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"func isPidScanError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"could not find PID for inode\")\n}","tryCatchPattern":"if err != nil && isPidScanError(err) {\n    // EACCES inside scan = hidden processes; fall back\n}","preventionTips":["Run with adequate privileges when cross-user matching is required","Do not enable process routing on systems with hidepid unless the caller is exempted"],"tags":["linux","process-lookup","permissions","procfs","race-condition"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}