XTLS/Xray-core · error
empty file
Error message
empty file
What it means
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.
Source
Thrown at common/geodata/rule_parser.go:66
}
func cutReversePrefix(s string) (string, bool) {
reverse := false
for strings.HasPrefix(s, "!") {
s = s[1:]
reverse = !reverse
}
return s, reverse
}
func parseGeoIPRule(rule string, reverse bool) (*IPRule_Geoip, error) {
file, code, ok := strings.Cut(rule, ":")
if !ok {
return nil, errors.New("syntax error")
}
if file == "" {
return nil, errors.New("empty file")
}
code, codeReverse := cutReversePrefix(code)
reverse = reverse != codeReverse
if code == "" {
return nil, errors.New("empty code")
}
code = strings.ToUpper(code)
if err := checkFile(file, code); err != nil {
return nil, err
}
return &IPRule_Geoip{
Geoip: &GeoIPRule{
File: file,
Code: code,
ReverseMatch: reverse,View on GitHub (pinned to 7d214f8b09)
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.
Example fix
// before "ip": [":cn"] // after "ip": ["geoip:cn"]
Defensive patterns
Strategy: validation
Validate before calling
for _, r := range rules {
body, _ := cutBangPrefix(r)
if strings.HasPrefix(body, ":") { return fmt.Errorf("rule %q: empty file segment", r) }
} Prevention
- Generate rules from (file, code) tuple variables instead of string concatenation.
When it happens
Trigger: Rule strings like ":cn", "!:ir", or "::cn" passed as IP rules; a typo where the filename before ':' was deleted but the colon kept.
Common situations: Hand-editing configs and deleting the "geoip" or "ext:file.dat" token while leaving the colon.
Related errors
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/49d821ad600892e1.
Report an issue: GitHub.