hashicorp/nomad · error

Invalid node pool capability '%s' for '%s'

Error message

Invalid node pool capability '%s' for '%s'

What it means

Returned by acl.Parse in acl/policy.go:629 when a node_pool stanza lists a capability not accepted by isNodePoolCapabilityValid (acl/policy.go:403). Node pool capabilities are limited to delete, read, write, and deny; everything else — including namespace capabilities — is rejected.

Source

Thrown at acl/policy.go:629

				pathPolicy.Capabilities = expandVariablesCapabilities(pathPolicy.Capabilities)

			}
		}

		// Remove the namespace name from the extra key list.
		p.removeExtraKey(ns.Name)
	}

	for _, np := range p.NodePools {
		if !validNodePool.MatchString(np.Name) {
			return nil, fmt.Errorf("Invalid node pool name '%s'", np.Name)
		}
		if np.Policy != "" && !isPolicyValid(np.Policy) {
			return nil, fmt.Errorf("Invalid node pool policy '%s' for '%s'", np.Policy, np.Name)
		}
		for _, cap := range np.Capabilities {
			if !isNodePoolCapabilityValid(cap) {
				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)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Use only read, write, delete, or deny in node_pool capabilities (exact lowercase)
  2. Remove or relocate namespace/variables capabilities into their proper stanzas
  3. Check for typos ('destroy' belongs to variables, not node pools)
  4. Pre-validate each capability against the four-value set before calling Parse

Example fix

// before
node_pool "prod" {
  capabilities = ["read", "destroy"]
}
// after
node_pool "prod" {
  capabilities = ["read", "delete"]
}
Defensive patterns

Strategy: validation

Validate before calling

var validPoolCaps = map[string]bool{"read": true, "write": true, "delete": true, "deny": true}
for _, np := range policy.NodePools {
    for _, c := range np.Capabilities {
        if !validPoolCaps[c] { return fmt.Errorf("node pool %s: bad capability %q", np.Name, c) }
    }
}

Prevention

When it happens

Trigger: Calling acl.Parse with node_pool { capabilities = [...] } containing values outside {read, write, delete, deny} — misspellings, uppercase, or namespace/variables capabilities pasted in.

Common situations: Copy-pasting capability lists between stanza types (namespace vs node_pool vs variables); typos like 'destory' or 'destroy' (variables-only word) in a node_pool stanza; tooling emitting a shared capability enum for all stanza types.

Related errors


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