XTLS/Xray-core · error
unknown action: {}
Error message
unknown action: {} What it means
Thrown while building a DNS rule in an Xray DNS outbound/proxy config: the rule's 'action' string did not match any of the supported keywords. The switch in DNSRuleConfig.Build() only accepts 'direct', 'drop', 'return', and 'hijack' (case-insensitive), and any other value falls into the default branch. This is a config parse/build error surfaced at startup when the JSON config is compiled into protobuf.
Source
Thrown at infra/conf/dns_proxy.go:33
QType *PortList `json:"qType"`
Domain *StringList `json:"domain"`
RCode uint32 `json:"rCode"`
}
func (c *DNSOutboundRuleConfig) Build() (*dns.DNSRuleConfig, error) {
rule := &dns.DNSRuleConfig{}
switch strings.ToLower(c.Action) {
case "direct":
rule.Action = dns.RuleAction_Direct
case "drop":
rule.Action = dns.RuleAction_Drop
case "return":
rule.Action = dns.RuleAction_Return
case "hijack":
rule.Action = dns.RuleAction_Hijack
default:
return nil, errors.New("unknown action: ", c.Action)
}
if c.QType != nil {
for _, r := range c.QType.Range {
for qType := r.From; qType <= r.To; qType++ {
rule.QType = append(rule.QType, int32(qType))
}
}
}
if c.Domain != nil {
rules, err := geodata.ParseDomainRules(*c.Domain, geodata.Domain_Substr)
if err != nil {
return nil, err
}
rule.Domain = rules
}
View on GitHub (pinned to 7d214f8b09)
Solutions
- Set "action" to one of exactly: "direct", "drop", "return", "hijack" (case-insensitive).
- For old 'reject' behavior use "return" with "rcode" (e.g. rcode 5 = REFUSED) instead of a reject action.
- If you want the query sent through normally, use "direct".
- Validate all action strings against the accepted set before feeding the config to Xray.
Example fix
// before
{"type": "field", "action": "reject", "qType": [255]}
// after
{"type": "field", "action": "return", "rcode": 5, "qType": [255]} Defensive patterns
Strategy: validation
Validate before calling
var validDNSActions = map[string]bool{"direct": true, "drop": true, "return": true, "hijack": true}
func validAction(a string) bool { return validDNSActions[strings.ToLower(strings.TrimSpace(a))] }
// before calling config Build / starting Xray:
for _, r := range dnsOutbound.Rules {
if !validAction(r.Action) {
log.Fatalf("invalid DNS rule action %q (want direct|drop|return|hijack)", r.Action)
}
} Prevention
- Keep a whitelist of the four action keywords in your config linter.
- Run `xray run -test -c config.json` in CI to catch build-time config errors.
- Prefer the rules syntax over legacy fields so actions are explicit.
When it happens
Trigger: A JSON DNS rule object whose "action" field is misspelled (e.g. "block", "reject", "allow", "Drop " with trailing space is OK since strings.ToLower is used but "dropp" is not) or uses a synonym that the engine does not know. Calling Build() on a DNSRuleConfig with an unrecognized Action string always returns this error.
Common situations: Migrating from older Xray/V2Ray DNS configs where 'reject' semantics were expressed differently; copy-pasting rule examples from other projects (sing-box, AdGuard) that use different action names; typos in hand-written JSON.
Related errors
- rCode out of range: {}
- unknown nonIPQuery: {}
- empty domains & empty resolvers
- invalid resolver + r
- bridge tag is empty
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/9577678d2015373a.
Report an issue: GitHub.