{"record":{"id":"49d821ad600892e1","repo":"XTLS/Xray-core","slug":"empty-file","errorCode":null,"errorMessage":"empty file","messagePattern":"empty file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/geodata/rule_parser.go","lineNumber":66,"sourceCode":"}\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, \":\")\n\tif !ok {\n\t\treturn nil, errors.New(\"syntax error\")\n\t}\n\n\tif file == \"\" {\n\t\treturn nil, errors.New(\"empty file\")\n\t}\n\n\tcode, codeReverse := cutReversePrefix(code)\n\treverse = reverse != codeReverse\n\tif code == \"\" {\n\t\treturn nil, errors.New(\"empty code\")\n\t}\n\tcode = strings.ToUpper(code)\n\n\tif err := checkFile(file, code); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &IPRule_Geoip{\n\t\tGeoip: &GeoIPRule{\n\t\t\tFile:         file,\n\t\t\tCode:         code,\n\t\t\tReverseMatch: reverse,","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/common/geodata/rule_parser.go#L48-L84","documentation":"After splitting a GeoIP rule at ':', the file part (before the colon) is empty. This happens when the rule starts with ':' — Cut succeeds but returns an empty first segment, e.g. \":cn\" after reverse-prefix stripping.","triggerScenarios":"Rule strings like \":cn\", \"!:ir\", or \"::cn\" passed as IP rules; a typo where the filename before ':' was deleted but the colon kept.","commonSituations":"Hand-editing configs and deleting the \"geoip\" or \"ext:file.dat\" token while leaving the colon.","solutions":["Supply the file segment: use \"geoip:cn\" or \"ext:custom.dat:cn\".","Delete the leading colon if a plain country-code was intended — plain codes are not valid; geoip: prefix is required."],"exampleFix":"// before\n\"ip\": [\":cn\"]\n\n// after\n\"ip\": [\"geoip:cn\"]","handlingStrategy":"validation","validationCode":"for _, r := range rules {\n    body, _ := cutBangPrefix(r)\n    if strings.HasPrefix(body, \":\") { return fmt.Errorf(\"rule %q: empty file segment\", r) }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate rules from (file, code) tuple variables instead of string concatenation."],"tags":["geodata","ip-rule","syntax","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}