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 collide

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Replace the invalid capability with one of: deny, mount-readonly, mount-readwrite.
  2. Alternatively drop capabilities entirely and use the shorthand policy = "read"|"write"|"deny", which expands to the right capabilities.
  3. 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

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/7a9a8fef73f58ecf. Report an issue: GitHub.