hashicorp/nomad · error

Invalid host volume policy: %#v

Error message

Invalid host volume policy: %#v

What it means

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.

Source

Thrown at acl/policy.go:647

				return nil, fmt.Errorf("Invalid node pool capability '%s' for '%s'", cap, np.Name)
			}
		}

		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)
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set policy to one of exactly: deny, read, write, or scale (lowercase).
  2. If you need mount granularity, remove the policy field and use capabilities = ["mount-readonly"] or ["mount-readwrite"] instead.
  3. Check the printed %#v struct to confirm which host_volume block carries the bad Policy value.

Example fix

// before
host_volume "data" {
  policy = "readonly"
}
// after
host_volume "data" {
  capabilities = ["mount-readonly"]
}
Defensive patterns

Strategy: validation

Validate before calling

var validPolicies = map[string]bool{"deny": true, "read": true, "write": true, "scale": true}
for _, hv := range policy.HostVolumes {
    if hv.Policy != "" && !validPolicies[hv.Policy] {
        return fmt.Errorf("host_volume %q: policy %q must be deny|read|write|scale", hv.Name, hv.Policy)
    }
}

Type guard

func isPolicyValid(policy string) bool {
    switch policy {
    case "deny", "read", "write", "scale":
        return true
    }
    return false
}

Try / catch

_, err := acl.Parse(rules, acl.PolicyParseStrict)
if err != nil {
    if strings.Contains(err.Error(), "Invalid host volume policy") {
        // log the bad shorthand policy and correct to deny|read|write|scale
    }
    return err
}

Prevention

When it happens

Trigger: acl.Parse on a policy containing host_volume "name" { policy = "<invalid>" } where the string is not exactly "deny", "read", "write", or "scale".

Common situations: 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.

Related errors


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