{"record":{"id":"5bd9e5e08ab1bd45","repo":"hashicorp/nomad","slug":"failed-to-construct-acl-v","errorCode":null,"errorMessage":"failed to construct ACL: %v","messagePattern":"failed to construct ACL: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/funcs.go","lineNumber":446,"sourceCode":"\tentry, ok := cache.Get(cacheKey)\n\tif ok {\n\t\treturn entry.Get(), nil\n\t}\n\n\t// Parse the policies\n\tparsed := make([]*acl.Policy, 0, len(policies))\n\tfor _, policy := range policies {\n\t\tp, err := acl.Parse(policy.Rules, acl.PolicyParseLenient)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse %q: %v\", policy.Name, err)\n\t\t}\n\t\tparsed = append(parsed, p)\n\t}\n\n\t// Create the ACL object\n\taclObj, err := acl.NewACL(false, parsed)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to construct ACL: %v\", err)\n\t}\n\n\t// Update the cache\n\tcache.Add(cacheKey, aclObj)\n\treturn aclObj, nil\n}\n\n// GenerateMigrateToken will create a token for a client to access an\n// authenticated volume of another client to migrate data for sticky volumes.\nfunc GenerateMigrateToken(allocID, nodeSecretID string) (string, error) {\n\th, err := blake2b.New512([]byte(nodeSecretID))\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t_, _ = h.Write([]byte(allocID))\n\n\treturn base64.URLEncoding.EncodeToString(h.Sum(nil)), nil","sourceCodeStart":428,"sourceCodeEnd":464,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/funcs.go#L428-L464","documentation":"CompileACLObject returns this when the parsed policies are individually valid HCL but acl.NewACL fails to build the combined ACL object — typically semantically invalid rule contents (e.g. bad glob patterns or deny/read conflicts the ACL constructor rejects). The token cannot be authorized until resolved.","triggerScenarios":"resolveTokenAndACL / resolveClaims / resolveACLFromToken call CompileACLObject and acl.NewACL(false, parsed) errors while combining the token's policies and any management/default policies.","commonSituations":"A policy containing invalid wildcard/glob patterns (e.g. over-broad '*' usage in disallowed fields) or inconsistent rule sets introduced by an edit; policies written by automation with corrupted rules.","solutions":["Read the wrapped %v detail to identify which rule acl.NewACL rejected","Fix glob patterns in the offending policy — check every pattern field for validity (e.g. 'namespace_prefix' vs plain 'namespace' usage)","Re-apply the corrected policy with 'nomad acl policy apply <name> <file>'","Narrow down by temporarily attaching only the suspect policy to a test token and compiling"],"exampleFix":"// before\nkey_prefix \"\" { policy = \"write\"; deny = true }\n// after\nkey_prefix \"\" { policy = \"deny\" }","handlingStrategy":"validation","validationCode":"// go: parse and construct locally before compiling the full set\nparsed := make([]*acl.Policy, 0, len(policies))\nfor _, p := range policies {\n    pp, err := acl.Parse(p.Rules, acl.PolicyParseLenient)\n    if err != nil { return fmt.Errorf(\"policy %q unparseable\", p.Name) }\n    parsed = append(parsed, pp)\n}\nif _, err := acl.NewACL(false, parsed); err != nil {\n    return fmt.Errorf(\"policies cannot combine into a valid ACL: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"aclObj, err := structs.CompileACLObject(cache, policies)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"failed to construct ACL\") {\n        // invalid rule semantics: review globs and deny rules\n    }\n    return err\n}","preventionTips":["Avoid invalid glob patterns in policy fields","Don't mix policy=\"deny\" with policy=\"write\" on overlapping prefixes; use policy=\"deny\" directly","Review every attached policy when a token suddenly fails authorization"],"tags":["nomad","acl","policy","construction"],"backgroundTag":"acl-policy-parse-failed","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"}