{"record":{"id":"1aa30e7bdf80fb2d","repo":"hashicorp/nomad","slug":"invalid-host-volume-policy-v","errorCode":null,"errorMessage":"Invalid host volume policy: %#v","messagePattern":"Invalid host volume policy: %#v","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"acl/policy.go","lineNumber":647,"sourceCode":"\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) {\n\t\t\treturn nil, fmt.Errorf(\"Invalid host volume name: %#v\", hv)\n\t\t}\n\t\tif hv.Policy != \"\" && !isPolicyValid(hv.Policy) {\n\t\t\treturn nil, fmt.Errorf(\"Invalid host volume policy: %#v\", hv)\n\t\t}\n\t\tfor _, cap := range hv.Capabilities {\n\t\t\tif !isHostVolumeCapabilityValid(cap) {\n\t\t\t\treturn nil, fmt.Errorf(\"Invalid host volume capability '%s': %#v\", cap, hv)\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 hv.Policy != \"\" {\n\t\t\textraCap := expandHostVolumePolicy(hv.Policy)\n\t\t\thv.Capabilities = append(hv.Capabilities, extraCap...)\n\t\t}\n\n\t\t// Remove the host-volume name from the extra key list.\n\t\tp.removeExtraKey(hv.Name)\n\t}\n","sourceCodeStart":629,"sourceCodeEnd":665,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/acl/policy.go#L629-L665","documentation":"acl.Parse() (acl/policy.go:647) checks each host_volume block's shorthand Policy field against the allowed values deny, read, write, scale via isPolicyValid. A non-empty policy string with any other value (typo, wrong case, or an invalid value like 'list') aborts parsing. Note that the Policy field is optional — it is only validated when non-empty.","triggerScenarios":"acl.Parse on a policy containing host_volume \"name\" { policy = \"<invalid>\" } where the string is not exactly \"deny\", \"read\", \"write\", or \"scale\".","commonSituations":"Typos such as 'Read' (capitalized) or 'readonly'; reusing capability names like 'mount-readonly' in the shorthand policy field instead of the capabilities list; copying a CSI/plugin policy value into a host_volume block.","solutions":["Set policy to one of exactly: deny, read, write, or scale (lowercase).","If you need mount granularity, remove the policy field and use capabilities = [\"mount-readonly\"] or [\"mount-readwrite\"] instead.","Check the printed %#v struct to confirm which host_volume block carries the bad Policy value."],"exampleFix":"// before\nhost_volume \"data\" {\n  policy = \"readonly\"\n}\n// after\nhost_volume \"data\" {\n  capabilities = [\"mount-readonly\"]\n}","handlingStrategy":"validation","validationCode":"var validPolicies = map[string]bool{\"deny\": true, \"read\": true, \"write\": true, \"scale\": true}\nfor _, hv := range policy.HostVolumes {\n    if hv.Policy != \"\" && !validPolicies[hv.Policy] {\n        return fmt.Errorf(\"host_volume %q: policy %q must be deny|read|write|scale\", hv.Name, hv.Policy)\n    }\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 host volume policy\") {\n        // log the bad shorthand policy and correct to deny|read|write|scale\n    }\n    return err\n}","preventionTips":["Only use the lowercase literals deny, read, write, scale in the policy field","Use capabilities = [\"mount-readonly\"|\"mount-readwrite\"] for fine-grained access instead of inventing policy values","Keep a shared constants list of valid policy strings in tooling that generates policies"],"tags":["nomad","acl","policy-validation","host-volume"],"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"}