hashicorp/nomad · error

Invalid variable capability '%s' in namespace %s

Error message

Invalid variable capability '%s' in namespace %s

What it means

Returned by acl.Parse in acl/policy.go:607 when a variables path block lists a capability not accepted by isPathCapabilityValid (acl/policy.go:314). Variables path capabilities are limited to write, read, list, destroy, and deny; any other string (including namespace capabilities like submit-job) is rejected.

Source

Thrown at acl/policy.go:607

		// Expand implicit capabilities
		expandNamespaceCapabilities(ns)

		if ns.Variables != nil {
			if len(ns.Variables.Paths) == 0 {
				return nil, fmt.Errorf("Invalid variable policy: no variable paths in namespace %s", ns.Name)
			}
			for _, pathPolicy := range ns.Variables.Paths {
				if pathPolicy.PathSpec == "" {
					return nil, fmt.Errorf("Invalid missing variable path in namespace %s", ns.Name)
				}
				if strings.HasPrefix(pathPolicy.PathSpec, "/") {
					return nil, fmt.Errorf(
						"Invalid variable path %q in namespace %s: cannot start with a leading '/'`",
						pathPolicy.PathSpec, ns.Name)
				}
				for _, cap := range pathPolicy.Capabilities {
					if !isPathCapabilityValid(cap) {
						return nil, fmt.Errorf(
							"Invalid variable capability '%s' in namespace %s", cap, ns.Name)
					}
				}
				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)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Use only read, write, list, destroy, or deny in variables path capabilities (exact lowercase)
  2. Replace 'delete' with 'destroy' (most common confusion)
  3. Move non-variable capabilities into the namespace stanza's capabilities list
  4. Pre-validate each capability against the fixed set of five before calling Parse

Example fix

// before
variables {
  path "secret/app" {
    capabilities = ["read", "delete"]
  }
}
// after
variables {
  path "secret/app" {
    capabilities = ["read", "destroy"]
  }
}
Defensive patterns

Strategy: validation

Validate before calling

var validVarCaps = map[string]bool{"read": true, "write": true, "list": true, "destroy": true, "deny": true}
for _, ns := range policy.Namespaces {
    if ns.Variables == nil { continue }
    for _, p := range ns.Variables.Paths {
        for _, c := range p.Capabilities {
            if !validVarCaps[c] { return fmt.Errorf("bad variables capability %q", c) }
        }
    }
}

Prevention

When it happens

Trigger: Calling acl.Parse with path { capabilities = [...] } in a variables stanza containing values outside {read, write, list, destroy, deny} — misspellings, uppercase forms, or namespace/node-pool capabilities pasted into a variables path.

Common situations: Copy-pasting namespace capabilities into variables stanzas; typos like 'delete' (correct word is 'destroy'); uppercase 'READ'; generators reusing a generic capability enum.

Related errors


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