{"record":{"id":"5a79ec1d2a7069b2","repo":"XTLS/Xray-core","slug":"illegal-ip-rule","errorCode":null,"errorMessage":"illegal ip rule: ","messagePattern":"illegal ip rule: ","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/geodata/rule_parser.go","lineNumber":42,"sourceCode":"\t\t}\n\n\t\tprefix := 0\n\t\tfor _, ext := range [...]string{\"ext:\", \"ext-ip:\"} {\n\t\t\tif strings.HasPrefix(r, ext) {\n\t\t\t\tprefix = len(ext)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tvar rule isIPRule_Value\n\t\tvar err error\n\t\tif prefix > 0 {\n\t\t\trule, err = parseGeoIPRule(r[prefix:], reverse)\n\t\t} else {\n\t\t\trule, err = parseCustomIPRule(r, reverse)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"illegal ip rule: \", rules[i]).Base(err)\n\t\t}\n\t\tipRules = append(ipRules, &IPRule{Value: rule})\n\t}\n\n\treturn ipRules, nil\n}\n\nfunc cutReversePrefix(s string) (string, bool) {\n\treverse := false\n\tfor strings.HasPrefix(s, \"!\") {\n\t\ts = s[1:]\n\t\treverse = !reverse\n\t}\n\treturn s, reverse\n}\n\nfunc parseGeoIPRule(rule string, reverse bool) (*IPRule_Geoip, error) {\n\tfile, code, ok := strings.Cut(rule, \":\")","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/common/geodata/rule_parser.go#L24-L60","documentation":"Wraps any failure from parseCustomIPRule/parseGeoIPRule while converting the i-th string of an IP rule list into a structured IRule. The offending raw rule text is embedded in the message, and the base error names the actual cause (syntax error, empty file/code, bad CIDR, etc.).","triggerScenarios":"ParseIPRules receiving strings like \"geoip:cn:\", \"ext:file.dat:\", \"!\", \"1.2.3.4/33\", or a plain token that is neither a CIDR nor an IP (e.g. \"not-an-ip\").","commonSituations":"Typos in route rules — missing country code after geoip:, forgotten : separator, prefix length > 32/128, using domain strings in the ip array by mistake.","solutions":["Read the base error and the echoed rule string; fix the specific sub-error (add missing code, fix CIDR).","Ensure IP rules use forms: \"geoip:CODE\", \"ext:FILE.dat:CODE\", optionally prefixed with '!', or plain IP/CIDR.","Run `xray run -test -c config.json` to validate before deploying."],"exampleFix":"// before\n\"ip\": [\"geoip:\", \"1.2.3.4/40\"]\n\n// after\n\"ip\": [\"geoip:cn\", \"1.2.3.4/32\"]","handlingStrategy":"validation","validationCode":"var ipRuleRe = regexp.MustCompile(`^(!+)?(geoip:[a-zA-Z]{2}|ext:[\\w.-]+\\.dat:!?[a-zA-Z]{2}|[0-9a-fA-F:.]+(/\\d+)?)$`)\nfor _, r := range rules {\n    if !ipRuleRe.MatchString(r) { return fmt.Errorf(\"suspicious ip rule %q\", r) }\n}","typeGuard":null,"tryCatchPattern":"if _, err := geodata.ParseIPRules(rules); err != nil { /* err message contains the raw rule; log and fail fast at startup */ }","preventionTips":["Run `xray run -test -c config.json` in CI.","Keep IP-rule vocabulary limited to geoip:/ext:/CIDR forms; reject anything else in your config generator."],"tags":["geodata","ip-rule","parsing","config","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}