{"record":{"id":"a86a01c58773fad4","repo":"XTLS/Xray-core","slug":"invalid-ip-format-for","errorCode":null,"errorMessage":"invalid IP format for : ","messagePattern":"invalid IP format for : ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/net/find_process_linux.go","lineNumber":94,"sourceCode":"\n\tpid, err := strconv.Atoi(pidStr)\n\tif err != nil {\n\t\treturn 0, \"\", \"\", errors.New(\"failed to parse PID: \", err)\n\t}\n\n\treturn pid, procName, absPath, nil\n}\n\nfunc formatLittleEndianString(addr net.IP, port Port) (string, error) {\n\tip := addr\n\tvar ipBytes []byte\n\tif ip.To4() != nil {\n\t\tipBytes = ip.To4()\n\t} else {\n\t\tipBytes = ip.To16()\n\t}\n\tif ipBytes == nil {\n\t\treturn \"\", errors.New(\"invalid IP format for \", addr, \": \", ip)\n\t}\n\n\tfor i, j := 0, len(ipBytes)-1; i < j; i, j = i+1, j-1 {\n\t\tipBytes[i], ipBytes[j] = ipBytes[j], ipBytes[i]\n\t}\n\tportHex := fmt.Sprintf(\"%04X\", uint16(port))\n\tipHex := strings.ToUpper(hex.EncodeToString(ipBytes))\n\treturn fmt.Sprintf(\"%s:%s\", ipHex, portHex), nil\n}\n\nfunc findInodeInFile(filePath, targetHexAddr string) (string, error) {\n\tfile, err := os.Open(filePath)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer file.Close()\n\n\tscanner := bufio.NewScanner(file)","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/common/net/find_process_linux.go#L76-L112","documentation":"formatLittleEndianString reports that the net.IP passed in produced no usable byte slice: To4() and To16() both returned nil, which for net.IP only happens when the input is nil (or a 4-byte/16-byte-malformed value). The message prints the original addr. The root cause is always an invalid or missing IP upstream — net.ParseIP never errors, it silently returns nil.","triggerScenarios":"FindProcess called with srcIP that net.ParseIP cannot parse ('', hostname, '1.2.3.4/24', IPv6 with zone). The nil flows silently until this formatting step.","commonSituations":"Call sites passing empty metadata strings for direct connections, addresses taken from proxy headers without validation, or IPs with CIDR or zone suffixes.","solutions":["Validate with net.ParseIP(srcIP) != nil before calling FindProcess","Normalize addresses upstream: strip CIDR length, zone IDs, and port suffixes","Fail fast at the boundary where srcIP enters your system rather than deep in process lookup"],"exampleFix":"// before\nerr := routeByProcess(srcIP, srcPort)\n\n// after\nip := net.ParseIP(srcIP)\nif ip == nil {\n    return fmt.Errorf(\"invalid source IP %q\", srcIP)\n}\nerr := routeByProcess(ip.String(), srcPort)","handlingStrategy":"validation","validationCode":"if net.ParseIP(srcIP) == nil {\n    return errors.New(\"invalid source IP: \", srcIP)\n}","typeGuard":"func isParsableIp(s string) bool {\n    return net.ParseIP(s) != nil // nil in = nil out = guaranteed failure later\n}","tryCatchPattern":null,"preventionTips":["net.ParseIP never returns an error — it returns nil; always check for nil","Reject empty srcIP early: it is the single most common cause of this error"],"tags":["linux","input-validation","ip-parsing","process-lookup"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}