{"record":{"id":"9675301a2643c4f7","repo":"XTLS/Xray-core","slug":"unknown-action-967530","errorCode":null,"errorMessage":"unknown action: ","messagePattern":"unknown action: ","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/freedom.go","lineNumber":261,"sourceCode":"\t\tNConfig.ApplyTo = \"ipv4\"\n\tcase \"ipv6\":\n\t\tNConfig.ApplyTo = \"ipv6\"\n\tdefault:\n\t\treturn nil, errors.New(\"Invalid applyTo, only ip/ipv4/ipv6 are supported\")\n\t}\n\treturn NConfig, nil\n}\n\nfunc (c *FreedomFinalRuleConfig) Build() (*freedom.FinalRuleConfig, error) {\n\trule := &freedom.FinalRuleConfig{}\n\n\tswitch strings.ToLower(c.Action) {\n\tcase \"allow\":\n\t\trule.Action = freedom.RuleAction_Allow\n\tcase \"block\":\n\t\trule.Action = freedom.RuleAction_Block\n\tdefault:\n\t\treturn nil, errors.New(\"unknown action: \", c.Action)\n\t}\n\n\tif c.Network != nil {\n\t\trule.Networks = c.Network.Build()\n\t}\n\n\tif c.Port != nil {\n\t\trule.PortList = c.Port.Build()\n\t}\n\n\tif c.IP != nil {\n\t\trules, err := geodata.ParseIPRules(*c.IP)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\trule.Ip = rules\n\t}\n","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/freedom.go#L243-L279","documentation":"Thrown by FreedomFinalRuleConfig.Build when the final rule's action field is neither 'allow' nor 'block' (case-insensitive). Final rules are a terminal allow/block decision for freedom traffic, so only those two actions exist; the action is required. Note the error uses errors.New with two args, so the message includes the offending action value after the prefix.","triggerScenarios":"Setting settings.final[].action to values like \"deny\", \"reject\", \"pass\", \"route\", or omitting it entirely (empty string falls into default).","commonSituations":"Users familiar with routing rule actions (e.g. 'reject') assuming the same vocabulary applies to freedom final rules; forgetting that a final rule with no action is invalid rather than defaulting to allow.","solutions":["Set the final rule's action to exactly \"allow\" or \"block\" (any casing; it is lowercased before matching)","Remove the final rule entry entirely if you do not need an explicit terminal decision"],"exampleFix":"// before\n\"final\": [ { \"action\": \"reject\" } ]\n// after\n\"final\": [ { \"action\": \"block\" } ]","handlingStrategy":"validation","validationCode":"func validFinalAction(a string) bool {\n\ts := strings.ToLower(a)\n\treturn s == \"allow\" || s == \"block\"\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat action as a required enum in config schemas (allow|block only)","Do not assume routing-rule action vocabulary applies to freedom final rules"],"tags":["xray","config","freedom","final-rule","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}