hashicorp/nomad · error
Invalid host volume capability '%s': %#v
Error message
Invalid host volume capability '%s': %#v
What it means
acl.Parse() (acl/policy.go:651) validates each entry of a host_volume block's Capabilities list with isHostVolumeCapabilityValid, which only accepts "deny", "mount-readonly", and "mount-readwrite". Any other capability string fails parsing and the policy is rejected with the whole HostVolumePolicy printed via %#v.
Source
Thrown at acl/policy.go:651
if np.Policy != "" {
extraCap := expandNodePoolPolicy(np.Policy)
np.Capabilities = append(np.Capabilities, extraCap...)
}
// Remove the node-pool name from the extra key list.
p.removeExtraKey(np.Name)
}
for _, hv := range p.HostVolumes {
if !validVolume.MatchString(hv.Name) {
return nil, fmt.Errorf("Invalid host volume name: %#v", hv)
}
if hv.Policy != "" && !isPolicyValid(hv.Policy) {
return nil, fmt.Errorf("Invalid host volume policy: %#v", hv)
}
for _, cap := range hv.Capabilities {
if !isHostVolumeCapabilityValid(cap) {
return nil, fmt.Errorf("Invalid host volume capability '%s': %#v", cap, hv)
}
}
// Expand the short hand policy to the capabilities and
// add to any existing capabilities
if hv.Policy != "" {
extraCap := expandHostVolumePolicy(hv.Policy)
hv.Capabilities = append(hv.Capabilities, extraCap...)
}
// Remove the host-volume name from the extra key list.
p.removeExtraKey(hv.Name)
}
// Now that we have processed all known keys, return an error if the
// operator wrote a policy with unknown keys if we are being strict. While
// these do not grant any extra privileges, it can be misleaing to allow
// these and cause problems later if we add new capabilities that collideView on GitHub (pinned to 482b49bf1a)
Solutions
- Replace the invalid capability with one of: deny, mount-readonly, mount-readwrite.
- Alternatively drop capabilities entirely and use the shorthand policy = "read"|"write"|"deny", which expands to the right capabilities.
- Read the '%s' in the error message to see exactly which capability string was rejected and fix that entry in the identified block.
Example fix
// before
host_volume "data" {
capabilities = ["mount", "read"]
}
// after
host_volume "data" {
capabilities = ["mount-readonly"]
} Defensive patterns
Strategy: validation
Validate before calling
var validHostVolCaps = map[string]bool{"deny": true, "mount-readonly": true, "mount-readwrite": true}
for _, hv := range policy.HostVolumes {
for _, c := range hv.Capabilities {
if !validHostVolCaps[c] {
return fmt.Errorf("host_volume %q: invalid capability %q", hv.Name, c)
}
}
} Type guard
func isHostVolumeCapabilityValid(cap string) bool {
switch cap {
case "deny", "mount-readonly", "mount-readwrite":
return true
}
return false
} Try / catch
_, err := acl.Parse(rules, acl.PolicyParseStrict)
if err != nil {
if strings.Contains(err.Error(), "Invalid host volume capability") {
// extract the quoted capability from the message and fix that entry
}
return err
} Prevention
- Only use deny, mount-readonly, mount-readwrite in host_volume capabilities
- Do not reuse namespace or CSI capability names in host_volume blocks
- Prefer the shorthand policy field unless you specifically need mount granularity
When it happens
Trigger: acl.Parse on a policy where a host_volume block's capabilities array contains an unrecognized string, e.g. capabilities = ["read"], ["mount"], or a namespace-style capability like "list-jobs".
Common situations: Confusing host-volume capabilities with namespace capabilities (e.g. 'host-volume-read'); inventing values like 'mount-ro'; version drift — older Nomad versions had no host_volume capabilities and a policy generated for a newer feature set uses unsupported entries.
Related errors
- Invalid host volume name: %#v
- Invalid host volume policy: %#v
- Invalid operator capability '%s'
- Invalid sentinel capability '%s'
- cannot register volume: node ID is required
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/7a9a8fef73f58ecf.
Report an issue: GitHub.