hashicorp/nomad · error

failed to parse %q: %v

Error message

failed to parse %q: %v

What it means

CompileACLObject parses each ACL policy's HCL rules with hashicorp's acl.Parse (lenient mode) and wraps any parse failure as 'failed to parse "<policy name>": <detail>'. It means one of the policies attached to a token is not valid ACL rules, so the token's effective ACL object cannot be compiled.

Source

Thrown at nomad/structs/funcs.go:438

func CompileACLObject(cache *ACLCache[*acl.ACL], policies []*ACLPolicy) (*acl.ACL, error) {
	// Sort the policies to ensure consistent ordering
	sort.Slice(policies, func(i, j int) bool {
		return policies[i].Name < policies[j].Name
	})

	// Determine the cache key
	cacheKey := ACLPolicyListHash(policies)
	entry, ok := cache.Get(cacheKey)
	if ok {
		return entry.Get(), nil
	}

	// Parse the policies
	parsed := make([]*acl.Policy, 0, len(policies))
	for _, policy := range policies {
		p, err := acl.Parse(policy.Rules, acl.PolicyParseLenient)
		if err != nil {
			return nil, fmt.Errorf("failed to parse %q: %v", policy.Name, err)
		}
		parsed = append(parsed, p)
	}

	// Create the ACL object
	aclObj, err := acl.NewACL(false, parsed)
	if err != nil {
		return nil, fmt.Errorf("failed to construct ACL: %v", err)
	}

	// Update the cache
	cache.Add(cacheKey, aclObj)
	return aclObj, nil
}

// GenerateMigrateToken will create a token for a client to access an
// authenticated volume of another client to migrate data for sticky volumes.
func GenerateMigrateToken(allocID, nodeSecretID string) (string, error) {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Fix the HCL in the named policy: validate the rules file with 'nomad acl policy apply' on a test cluster or hclfmt-style review
  2. Ensure the policy uses only supported stanzas (namespace/node/agent/service/key/quotas/etc.) with correct rule syntax like 'policy = "read"'
  3. Delete and re-create the broken policy via 'nomad acl policy delete <name>' then re-apply a corrected file
  4. If the policy came from workload identity claims, fix the claims-to-policy mapping/template

Example fix

// before (my-policy.hcl)
namespace "*" { polic = "read" }
// after
namespace "*" { policy = "read" }
Defensive patterns

Strategy: validation

Validate before calling

// go: parse policy rules locally before applying
if _, err := acl.Parse(policyRules, acl.PolicyParseLenient); err != nil {
    return fmt.Errorf("invalid policy HCL for %q: %v", name, err)
}

Try / catch

aclObj, err := structs.CompileACLObject(cache, policies)
if err != nil {
    // err names the offending policy inside the message; surface it to the operator
    return fmt.Errorf("token unusable: %w", err)
}

Prevention

When it happens

Trigger: resolveTokenAndACL / resolveClaims / resolveACLFromToken call CompileACLObject and acl.Parse(policy.Rules) returns an error for the named policy — e.g. malformed HCL, bad stanza names, or corrupted policy stored in state.

Common situations: Submitting an ACL policy with HCL syntax mistakes ('nomad acl policy apply' with a broken file); upgrading Nomad and an old policy uses a rule no longer parseable; claims-derived policies with malformed rules.

Understand the failure class

Related errors


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