{"record":{"id":"2d6a18c0b0814513","repo":"hashicorp/nomad","slug":"invalid-acl-policy-v","errorCode":null,"errorMessage":"invalid acl policy: %v","messagePattern":"invalid acl policy: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"acl/policy.go","lineNumber":736,"sourceCode":"\t\t\tp.Sentinel.Capabilities = append(p.Sentinel.Capabilities, extraCap...)\n\t\t}\n\t}\n\n\tif p.Quota != nil && !isPolicyValid(p.Quota.Policy) {\n\t\treturn nil, fmt.Errorf(\"Invalid quota policy: %#v\", p.Quota)\n\t}\n\n\tif p.Plugin != nil && !p.Plugin.isValid() {\n\t\treturn nil, fmt.Errorf(\"Invalid plugin policy: %#v\", p.Plugin)\n\t}\n\treturn p, nil\n}\n\n// hclDecode wraps hcl.Decode function but handles any unexpected panics\nfunc hclDecode(p *Policy, rules string) (err error) {\n\tdefer func() {\n\t\tif rerr := recover(); rerr != nil {\n\t\t\terr = fmt.Errorf(\"invalid acl policy: %v\", rerr)\n\t\t}\n\t}()\n\n\tif err = hcl.Decode(p, rules); err != nil {\n\t\treturn err\n\t}\n\n\t// Manually parse the policy to fix blocks without labels.\n\t//\n\t// Due to a bug in the way HCL decodes files, a block without a label may\n\t// return an incorrect key value and make it impossible to determine if the\n\t// key was set by the user or incorrectly set by the decoder.\n\t//\n\t// By manually parsing the file we are able to determine if the label is\n\t// missing in the file and set them to an empty string so the policy\n\t// validation can return the appropriate errors.\n\troot, err := hcl.Parse(rules)\n\tif err != nil {","sourceCodeStart":718,"sourceCodeEnd":754,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/acl/policy.go#L718-L754","documentation":"This error is produced by hclDecode in acl/policy.go, which wraps hcl.Decode in a recover() handler. When the HCL decoder panics while parsing ACL policy rules, the panic value is converted into \"invalid acl policy: %v\". It propagates up through NewACL (including construction of the package-level ManagementACL in acl/acl.go init).","triggerScenarios":"Calling NewACL (or TestACL variants) with rules that make the HCL parser panic — deeply malformed or structurally invalid policy input that hcl.Decode cannot handle gracefully.","commonSituations":"Corrupted or truncated ACL policy definitions; binary garbage or non-HCL content passed as rules; a regression where policies built programmatically trigger a library panic.","solutions":["Inspect the panic message appended after 'invalid acl policy:' to locate the malformed input.","Validate the policy rules as well-formed HCL before passing them to NewACL.","If triggered inside Consul startup (init of ManagementACL), verify the installed consul/acl package version and upgrade, since ManagementACL uses nil rules and panics here indicate a library bug."],"exampleFix":"// before\nacl, err := acl.NewACL(false, []byte(garbageRules))\n// after\nif !hclutil.ValidRules(rules) { return fmt.Errorf(\"rejecting malformed policy input\") }\nacl, err := acl.NewACL(false, rules)","handlingStrategy":"try-catch","validationCode":"// sanity-check input is plausibly HCL before NewACL\nif len(rules) == 0 || (!strings.Contains(string(rules), \"key_prefix\") && !strings.Contains(string(rules), \"service\") && !strings.Contains(string(rules), \"node\")) {\n    return fmt.Errorf(\"input does not look like ACL policy HCL\")\n}","typeGuard":null,"tryCatchPattern":"// NewACL already recovers panics into this error\np, err := acl.NewACL(isManagement, rules)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"invalid acl policy:\") {\n        return fmt.Errorf(\"policy input rejected: %w\", err)\n    }\n    return err\n}","preventionTips":["Never feed raw, untrusted bytes directly into NewACL.","Validate HCL syntax upstream with hcl.Parse before constructing ACLs.","Pin your consul/acl library version and watch for decoder panic fixes."],"tags":["acl","hcl","panic","consul"],"backgroundTag":"hcl-parse-panic","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}