{"record":{"id":"77c12f1d916f822e","repo":"hashicorp/nomad","slug":"invalid-node-pool-policy-s-for-s","errorCode":null,"errorMessage":"Invalid node pool policy '%s' for '%s'","messagePattern":"Invalid node pool policy '(.+?)' for '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"acl/policy.go","lineNumber":625,"sourceCode":"\t\t\t\t\t\treturn nil, fmt.Errorf(\n\t\t\t\t\t\t\t\"Invalid variable capability '%s' in namespace %s\", cap, ns.Name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpathPolicy.Capabilities = expandVariablesCapabilities(pathPolicy.Capabilities)\n\n\t\t\t}\n\t\t}\n\n\t\t// Remove the namespace name from the extra key list.\n\t\tp.removeExtraKey(ns.Name)\n\t}\n\n\tfor _, np := range p.NodePools {\n\t\tif !validNodePool.MatchString(np.Name) {\n\t\t\treturn nil, fmt.Errorf(\"Invalid node pool name '%s'\", np.Name)\n\t\t}\n\t\tif np.Policy != \"\" && !isPolicyValid(np.Policy) {\n\t\t\treturn nil, fmt.Errorf(\"Invalid node pool policy '%s' for '%s'\", np.Policy, np.Name)\n\t\t}\n\t\tfor _, cap := range np.Capabilities {\n\t\t\tif !isNodePoolCapabilityValid(cap) {\n\t\t\t\treturn nil, fmt.Errorf(\"Invalid node pool capability '%s' for '%s'\", cap, np.Name)\n\t\t\t}\n\t\t}\n\n\t\tif np.Policy != \"\" {\n\t\t\textraCap := expandNodePoolPolicy(np.Policy)\n\t\t\tnp.Capabilities = append(np.Capabilities, extraCap...)\n\t\t}\n\n\t\t// Remove the node-pool name from the extra key list.\n\t\tp.removeExtraKey(np.Name)\n\t}\n\n\tfor _, hv := range p.HostVolumes {\n\t\tif !validVolume.MatchString(hv.Name) {","sourceCodeStart":607,"sourceCodeEnd":643,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/acl/policy.go#L607-L643","documentation":"Returned by acl.Parse in acl/policy.go:625 when a node_pool stanza's policy shorthand is non-empty but not one of deny, read, write, or scale per isPolicyValid. Note the valid set for node pools in this check mirrors namespaces; the second %s in the message names the offending pool.","triggerScenarios":"Calling acl.Parse with node_pool { policy = \"...\" } set to a value outside {deny, read, write, scale} — e.g. \"list\", \"rw\", \"admin\", or wrong-case variants.","commonSituations":"Copy-pasting policy words from other stanza types or other HashiCorp products; typos like 'wrtie'; assuming plugin-style 'list' policy applies to node pools (it does not); older Nomad versions lacking 'scale'.","solutions":["Set policy to one of: deny, read, write, scale (exact lowercase)","Use explicit capabilities = [\"read\", \"write\", \"delete\", \"deny\"] instead of shorthand if fine-grained control is needed","Verify against the Nomad version's supported node-pool policy keywords"],"exampleFix":"// before\nnode_pool \"prod\" {\n  policy = \"admin\"\n}\n// after\nnode_pool \"prod\" {\n  policy = \"write\"\n}","handlingStrategy":"validation","validationCode":"var validPoolPolicies = map[string]bool{\"deny\": true, \"read\": true, \"write\": true, \"scale\": true}\nfor _, np := range policy.NodePools {\n    if np.Policy != \"\" && !validPoolPolicies[np.Policy] {\n        return fmt.Errorf(\"node pool %s: policy %q not in deny|read|write|scale\", np.Name, np.Policy)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use only exact lowercase deny/read/write/scale for node_pool policy shorthand","Use explicit capabilities (read/write/delete/deny) for fine-grained grants","Pin a policy schema in CI that rejects unknown policy keywords"],"tags":["nomad","acl","node-pool","policy-validation"],"backgroundTag":"acl-policy-validation-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"}