hashicorp/nomad · error

invalid acl policy: %v

Error message

invalid acl policy: %v

What it means

This error is produced by hclDecode in acl/policy.go, which wraps hcl.Decode in a recover() handler. When the HCL decoder panics while parsing ACL policy rules, the panic value is converted into "invalid acl policy: %v". It propagates up through NewACL (including construction of the package-level ManagementACL in acl/acl.go init).

Source

Thrown at acl/policy.go:736

			p.Sentinel.Capabilities = append(p.Sentinel.Capabilities, extraCap...)
		}
	}

	if p.Quota != nil && !isPolicyValid(p.Quota.Policy) {
		return nil, fmt.Errorf("Invalid quota policy: %#v", p.Quota)
	}

	if p.Plugin != nil && !p.Plugin.isValid() {
		return nil, fmt.Errorf("Invalid plugin policy: %#v", p.Plugin)
	}
	return p, nil
}

// hclDecode wraps hcl.Decode function but handles any unexpected panics
func hclDecode(p *Policy, rules string) (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = fmt.Errorf("invalid acl policy: %v", rerr)
		}
	}()

	if err = hcl.Decode(p, rules); err != nil {
		return err
	}

	// Manually parse the policy to fix blocks without labels.
	//
	// Due to a bug in the way HCL decodes files, a block without a label may
	// return an incorrect key value and make it impossible to determine if the
	// key was set by the user or incorrectly set by the decoder.
	//
	// By manually parsing the file we are able to determine if the label is
	// missing in the file and set them to an empty string so the policy
	// validation can return the appropriate errors.
	root, err := hcl.Parse(rules)
	if err != nil {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the panic message appended after 'invalid acl policy:' to locate the malformed input.
  2. Validate the policy rules as well-formed HCL before passing them to NewACL.
  3. If triggered inside Consul startup (init of ManagementACL), verify the installed consul/acl package version and upgrade, since ManagementACL uses nil rules and panics here indicate a library bug.

Example fix

// before
acl, err := acl.NewACL(false, []byte(garbageRules))
// after
if !hclutil.ValidRules(rules) { return fmt.Errorf("rejecting malformed policy input") }
acl, err := acl.NewACL(false, rules)
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check input is plausibly HCL before NewACL
if len(rules) == 0 || (!strings.Contains(string(rules), "key_prefix") && !strings.Contains(string(rules), "service") && !strings.Contains(string(rules), "node")) {
    return fmt.Errorf("input does not look like ACL policy HCL")
}

Try / catch

// NewACL already recovers panics into this error
p, err := acl.NewACL(isManagement, rules)
if err != nil {
    if strings.HasPrefix(err.Error(), "invalid acl policy:") {
        return fmt.Errorf("policy input rejected: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling NewACL (or TestACL variants) with rules that make the HCL parser panic — deeply malformed or structurally invalid policy input that hcl.Decode cannot handle gracefully.

Common situations: Corrupted or truncated ACL policy definitions; binary garbage or non-HCL content passed as rules; a regression where policies built programmatically trigger a library panic.

Related errors


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