hashicorp/nomad · error
Invalid operator capability '%s'
Error message
Invalid operator capability '%s'
What it means
acl.Parse (acl/policy.go:692) checks each entry of the operator block's Capabilities list with isOperatorCapabilityValid, which only accepts deny, snapshot-save, keyring-rotate, keyring-read, keyring-delete, and license-read. Any other capability string fails parsing and rejects the whole policy.
Source
Thrown at acl/policy.go:692
}
p.ExtraKeysHCL = nil
if p.Agent != nil && !isPolicyValid(p.Agent.Policy) {
return nil, fmt.Errorf("Invalid agent policy: %#v", p.Agent)
}
if p.Node != nil && !isPolicyValid(p.Node.Policy) {
return nil, fmt.Errorf("Invalid node policy: %#v", p.Node)
}
if p.Operator != nil {
if p.Operator.Policy != "" && !isPolicyValid(p.Operator.Policy) {
return nil, fmt.Errorf("Invalid operator policy: %#v", p.Operator)
}
for _, cap := range p.Operator.Capabilities {
if !isOperatorCapabilityValid(cap) {
return nil, fmt.Errorf("Invalid operator capability '%s'", cap)
}
}
// Expand the short hand policy to the capabilities and
// add to any existing capabilities
if p.Operator.Policy != "" {
extraCap := expandOperatorPolicy(p.Operator.Policy)
p.Operator.Capabilities = append(p.Operator.Capabilities, extraCap...)
}
}
if p.Sentinel != nil {
if p.Sentinel.Policy != "" && !isPolicyValid(p.Sentinel.Policy) {
return nil, fmt.Errorf("Invalid sentinel policy: %#v", p.Sentinel)
}
for _, cap := range p.Sentinel.Capabilities {
if !isSentinelCapabilityValid(cap) {
return nil, fmt.Errorf("Invalid sentinel capability '%s'", cap)View on GitHub (pinned to 482b49bf1a)
Solutions
- Replace the invalid capability with one of exactly: deny, snapshot-save, keyring-rotate, keyring-read, keyring-delete, license-read.
- Alternatively remove capabilities and use shorthand policy = "read"|"write"|"deny".
- The '%s' in the error names the exact rejected capability — fix that entry.
Example fix
// before
operator {
capabilities = ["snapshot"]
}
// after
operator {
capabilities = ["snapshot-save"]
} Defensive patterns
Strategy: validation
Validate before calling
var validOperatorCaps = map[string]bool{"deny": true, "snapshot-save": true, "keyring-rotate": true,
"keyring-read": true, "keyring-delete": true, "license-read": true}
if policy.Operator != nil {
for _, c := range policy.Operator.Capabilities {
if !validOperatorCaps[c] {
return fmt.Errorf("invalid operator capability %q", c)
}
}
} Type guard
func isOperatorCapabilityValid(cap string) bool {
switch cap {
case "deny", "snapshot-save", "keyring-rotate", "keyring-read", "keyring-delete", "license-read":
return true
}
return false
} Try / catch
_, err := acl.Parse(rules, acl.PolicyParseStrict)
if err != nil {
if strings.Contains(err.Error(), "Invalid operator capability") {
// fix the quoted capability name in the operator block
}
return err
} Prevention
- Use the exact capability literals: deny, snapshot-save, keyring-rotate, keyring-read, keyring-delete, license-read
- Remember license-read is Enterprise-only; don't ship it in OSS-only policy sets
- Centralize capability constants in tooling instead of hand-typing them
When it happens
Trigger: acl.Parse on a policy where operator { capabilities = [...] } contains an unrecognized string such as 'snapshot', 'license-manager', or a namespace capability like 'submit-job'.
Common situations: Typos or shortened forms of capability names ('snapshot' vs 'snapshot-save'); version drift — 'license-read' only exists in Nomad Enterprise/newer versions, so policies generated elsewhere may carry unsupported entries; confusing operator capabilities with node-pool or sentinel capabilities.
Related errors
- Invalid host volume capability '%s': %#v
- Invalid operator policy: %#v
- Invalid sentinel capability '%s'
- eval broker is enabled; eval broker must be paused to delete
- ACL policy not found
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/3008e1c6cea996a8.
Report an issue: GitHub.