{"record":{"id":"25e24621da2dde0b","repo":"hashicorp/nomad","slug":"invalid-sentinel-policy-v","errorCode":null,"errorMessage":"Invalid sentinel policy: %#v","messagePattern":"Invalid sentinel policy: %#v","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"acl/policy.go","lineNumber":706,"sourceCode":"\t\t\treturn nil, fmt.Errorf(\"Invalid operator policy: %#v\", p.Operator)\n\t\t}\n\t\tfor _, cap := range p.Operator.Capabilities {\n\t\t\tif !isOperatorCapabilityValid(cap) {\n\t\t\t\treturn nil, fmt.Errorf(\"Invalid operator capability '%s'\", cap)\n\t\t\t}\n\t\t}\n\n\t\t// Expand the short hand policy to the capabilities and\n\t\t// add to any existing capabilities\n\t\tif p.Operator.Policy != \"\" {\n\t\t\textraCap := expandOperatorPolicy(p.Operator.Policy)\n\t\t\tp.Operator.Capabilities = append(p.Operator.Capabilities, extraCap...)\n\t\t}\n\t}\n\n\tif p.Sentinel != nil {\n\t\tif p.Sentinel.Policy != \"\" && !isPolicyValid(p.Sentinel.Policy) {\n\t\t\treturn nil, fmt.Errorf(\"Invalid sentinel policy: %#v\", p.Sentinel)\n\t\t}\n\t\tfor _, cap := range p.Sentinel.Capabilities {\n\t\t\tif !isSentinelCapabilityValid(cap) {\n\t\t\t\treturn nil, fmt.Errorf(\"Invalid sentinel capability '%s'\", cap)\n\t\t\t}\n\t\t}\n\n\t\t// Expand the short hand policy to the capabilities and\n\t\t// add to any existing capabilities\n\t\tif p.Sentinel.Policy != \"\" {\n\t\t\textraCap := expandSentinelPolicy(p.Sentinel.Policy)\n\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}","sourceCodeStart":688,"sourceCodeEnd":724,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/acl/policy.go#L688-L724","documentation":"acl.Parse (acl/policy.go:706) validates the top-level sentinel block's Policy string with isPolicyValid, which only accepts deny, read, write, scale. A non-empty sentinel policy with any other value fails parsing and rejects the whole policy. Sentinel blocks are Nomad Enterprise features, so this typically surfaces in enterprise policy files.","triggerScenarios":"acl.Parse on a policy containing sentinel { policy = \"<invalid>\" } where the value is not exactly \"deny\", \"read\", \"write\", or \"scale\" — e.g. 'submit', 'sentinel-read', or an empty string set by a template.","commonSituations":"Putting sentinel capability names (sentinel-submit, sentinel-delete) into the policy field instead of the capabilities list; case mistakes; OSS Nomad users pasting an enterprise example policy verbatim with modified values.","solutions":["Set policy to one of exactly: deny, read, write, scale (lowercase).","For granular Sentinel permissions, use capabilities = [\"sentinel-read\", \"sentinel-submit\", \"sentinel-delete\"] instead of the shorthand.","Check the %#v struct in the error to identify the offending value."],"exampleFix":"// before\nsentinel {\n  policy = \"submit\"\n}\n// after\nsentinel {\n  capabilities = [\"sentinel-submit\"]\n}","handlingStrategy":"validation","validationCode":"if policy.Sentinel != nil && policy.Sentinel.Policy != \"\" &&\n    !map[string]bool{\"deny\": true, \"read\": true, \"write\": true, \"scale\": true}[policy.Sentinel.Policy] {\n    return fmt.Errorf(\"sentinel policy %q must be deny|read|write|scale\", policy.Sentinel.Policy)\n}","typeGuard":"func isPolicyValid(policy string) bool {\n    switch policy {\n    case \"deny\", \"read\", \"write\", \"scale\":\n        return true\n    }\n    return false\n}","tryCatchPattern":"_, err := acl.Parse(rules, acl.PolicyParseStrict)\nif err != nil {\n    if strings.Contains(err.Error(), \"Invalid sentinel policy\") {\n        // replace the sentinel shorthand policy or switch to capabilities\n    }\n    return err\n}","preventionTips":["Use only deny, read, write, scale in the sentinel policy field","Use capabilities = [\"sentinel-...\"] for submit/delete grants instead of the policy shorthand","Note sentinel blocks require Nomad Enterprise — validate the target edition supports them"],"tags":["nomad","acl","policy-validation","sentinel","enterprise"],"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"}