{"record":{"id":"aba6baf5c5ac4839","repo":"XTLS/Xray-core","slug":"illegal-domain-rule","errorCode":null,"errorMessage":"illegal domain rule: ","messagePattern":"illegal domain rule: ","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/geodata/rule_parser.go","lineNumber":156,"sourceCode":"\t}\n\n\tprefix := 0\n\tfor _, ext := range [...]string{\"ext:\", \"ext-domain:\", \"ext-site:\"} {\n\t\tif strings.HasPrefix(r, ext) {\n\t\t\tprefix = len(ext)\n\t\t\tbreak\n\t\t}\n\t}\n\n\tvar rule isDomainRule_Value\n\tvar err error\n\tif prefix > 0 {\n\t\trule, err = parseGeoSiteRule(r[prefix:])\n\t} else {\n\t\trule, err = parseCustomDomainRule(r, defaultType)\n\t}\n\tif err != nil {\n\t\treturn nil, errors.New(\"illegal domain rule: \", r).Base(err)\n\t}\n\treturn &DomainRule{Value: rule}, nil\n}\n\nfunc ParseDomainRules(rules []string, defaultType Domain_Type) ([]*DomainRule, error) {\n\tvar domainRules []*DomainRule\n\n\tfor i, r := range rules {\n\t\tif strings.HasPrefix(r, \"geosite:\") {\n\t\t\tr = \"ext:\" + DefaultGeoSiteDat + \":\" + r[len(\"geosite:\"):]\n\t\t}\n\n\t\tprefix := 0\n\t\tfor _, ext := range [...]string{\"ext:\", \"ext-domain:\", \"ext-site:\"} {\n\t\t\tif strings.HasPrefix(r, ext) {\n\t\t\t\tprefix = len(ext)\n\t\t\t\tbreak\n\t\t\t}","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/common/geodata/rule_parser.go#L138-L174","documentation":"ParseDomainRule wraps any failure from parseGeoSiteRule or parseCustomDomainRule for a single domain rule string. The full raw rule is echoed in the message and the base error carries the concrete cause (syntax error, empty file/code/attr, bad regex, etc.).","triggerScenarios":"Domain rules like \"geosite:\", \"ext:gs.dat:\", \"regex:[unclosed\", \"dotless:a.b\", or an invalid punycode/IDN string.","commonSituations":"Typos in the domain array of routing rules; mixing IP syntax into domain rules; unsupported attr suffixes like \"geosite:cn@\".","solutions":["Read the base error; fix the specific sub-problem (missing code after geosite:, unclosed regex, etc.).","Use supported forms: plain domain, \"domain:\", \"full:\", \"keyword:\", \"regexp:\", \"geosite:CODE\", \"ext:FILE:CODE[@attrs]\".","Validate config with `xray run -test -c config.json`."],"exampleFix":"// before\n\"domain\": [\"geosite:\"]\n\n// after\n\"domain\": [\"geosite:cn\"]","handlingStrategy":"validation","validationCode":"if _, err := geodata.ParseDomainRule(rule, Domain_Full); err != nil {\n    return fmt.Errorf(\"config rejected: bad domain rule %q: %w\", rule, err)\n}","typeGuard":null,"tryCatchPattern":"Wrap ParseDomainRule calls at config-load time and abort startup with the echoed rule string rather than retrying at runtime.","preventionTips":["Restrict domain rule syntax to the documented prefixes; lint with xray run -test."],"tags":["geodata","domain-rule","parsing","config","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}