hashicorp/nomad · error
Invalid policy: %s
Error message
Invalid policy: %s
What it means
acl/policy.go:565 (Parse) returns 'Invalid policy: %s' (with the raw policy text) when the policy decodes as valid HCL but parses to an empty policy (p.IsEmpty()) — i.e., it contains no actual rules. Nomad refuses to store rule-less policies because they would be meaningless placeholders.
Source
Thrown at acl/policy.go:565
// constants PolicyParseStrict and PolicyParseLenient can be used to make the
// intent clear at the call site.
func Parse(rules string, strict bool) (*Policy, error) {
// Decode the rules
p := &Policy{Raw: rules}
if rules == "" {
// Hot path for empty rules
return p, nil
}
// Attempt to parse
if err := hclDecode(p, rules); err != nil {
return nil, fmt.Errorf("Failed to parse ACL Policy: %v", err)
}
// At least one valid policy must be specified, we don't want to store only
// raw data
if p.IsEmpty() {
return nil, fmt.Errorf("Invalid policy: %s", p.Raw)
}
// Validate the policy
for _, ns := range p.Namespaces {
if !validNamespace.MatchString(ns.Name) {
return nil, fmt.Errorf("Invalid namespace name: %#v", ns)
}
if ns.Policy != "" && !isPolicyValid(ns.Policy) {
return nil, fmt.Errorf("Invalid namespace policy: %#v", ns)
}
for _, cap := range ns.Capabilities {
if !isNamespaceCapabilityValid(cap) {
return nil, fmt.Errorf("Invalid namespace capability '%s': %#v", cap, ns)
}
}
// Expand the short hand policy to the capabilities and
// add to any existing capabilitiesView on GitHub (pinned to 482b49bf1a)
Solutions
- Include at least one real rule stanza (namespace/node/service/host_volume/variables etc.) in the policy
- Fix the templating pipeline that produced an empty/whitespace-only rules document
- Verify with nomad acl policy apply after ensuring the file has actual content
Example fix
// before
# only comments in rules.hcl
# namespace "default" { ... }
// after
namespace "default" {
policy = "read"
} Defensive patterns
Strategy: validation
Validate before calling
// ensure the policy has at least one rule before submitting
if strings.TrimSpace(stripComments(rules)) == "" { return errors.New("policy has no rules") } Try / catch
if _, err := acl.ParsePolicy(rules); err != nil {
if strings.HasPrefix(err.Error(), "Invalid policy:") {
return fmt.Errorf("rules file rendered empty — check templates: %w", err)
}
return err
} Prevention
- Never ship comment-only or empty policy files
- Assert templated policies contain at least one stanza in CI
- Inspect rendered policy artifacts when generating rules dynamically
When it happens
Trigger: Applying an ACL policy whose rules contain only comments, whitespace, or empty stanzas; a template/variable interpolation that evaluated to nothing; passing an empty or comments-only rules file to nomad acl policy apply.
Common situations: CI pipelines templating policies where variables were empty, yielding comments-only output; truncation of the rules file upstream; accidentally applying an example file that documents policy format only in comments.
Related errors
- errMissingACLRoleID
- errMissingACLAuthMethodName
- errMissingACLBindingRuleID
- cannot specify ACL role ID
- missing ACL role name
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/8be0d9d2fc2e389c.
Report an issue: GitHub.