{"record":{"id":"9577678d2015373a","repo":"XTLS/Xray-core","slug":"unknown-action","errorCode":null,"errorMessage":"unknown action: {}","messagePattern":"unknown action: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/dns_proxy.go","lineNumber":33,"sourceCode":"\tQType  *PortList   `json:\"qType\"`\n\tDomain *StringList `json:\"domain\"`\n\tRCode  uint32      `json:\"rCode\"`\n}\n\nfunc (c *DNSOutboundRuleConfig) Build() (*dns.DNSRuleConfig, error) {\n\trule := &dns.DNSRuleConfig{}\n\n\tswitch strings.ToLower(c.Action) {\n\tcase \"direct\":\n\t\trule.Action = dns.RuleAction_Direct\n\tcase \"drop\":\n\t\trule.Action = dns.RuleAction_Drop\n\tcase \"return\":\n\t\trule.Action = dns.RuleAction_Return\n\tcase \"hijack\":\n\t\trule.Action = dns.RuleAction_Hijack\n\tdefault:\n\t\treturn nil, errors.New(\"unknown action: \", c.Action)\n\t}\n\n\tif c.QType != nil {\n\t\tfor _, r := range c.QType.Range {\n\t\t\tfor qType := r.From; qType <= r.To; qType++ {\n\t\t\t\trule.QType = append(rule.QType, int32(qType))\n\t\t\t}\n\t\t}\n\t}\n\n\tif c.Domain != nil {\n\t\trules, err := geodata.ParseDomainRules(*c.Domain, geodata.Domain_Substr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\trule.Domain = rules\n\t}\n","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/dns_proxy.go#L15-L51","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n{\"type\": \"field\", \"action\": \"reject\", \"qType\": [255]}\n\n// after\n{\"type\": \"field\", \"action\": \"return\", \"rcode\": 5, \"qType\": [255]}","handlingStrategy":"validation","validationCode":"var validDNSActions = map[string]bool{\"direct\": true, \"drop\": true, \"return\": true, \"hijack\": true}\n\nfunc validAction(a string) bool { return validDNSActions[strings.ToLower(strings.TrimSpace(a))] }\n\n// before calling config Build / starting Xray:\nfor _, r := range dnsOutbound.Rules {\n    if !validAction(r.Action) {\n        log.Fatalf(\"invalid DNS rule action %q (want direct|drop|return|hijack)\", r.Action)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["go","xray","dns","config","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}