hashicorp/nomad · error

ACL binding rule lookup failed

Error message

ACL binding rule lookup failed: %v

What it means

Returned by upsertACLBindingRuleTxn when the memdb lookup of an existing binding rule by ID fails (not when none exists). This check prevents accidental ID collisions before insert/update; the wrapped error indicates an internal lookup problem.

Solutions

  1. Inspect the wrapped memdb error for the root cause.
  2. Retry after ensuring consistent server versions.
  3. Restore the state store from a snapshot if the error persists.
Defensive patterns

Strategy: retry

Validate before calling

if rule.ID == "" { return errors.New("binding rule ID required") }

Try / catch

err := upsertRule(rule)
if err != nil && strings.Contains(err.Error(), "ACL binding rule lookup failed") {
    retryWithBackoff(upsertRule, rule)
}

Prevention

When it happens

Trigger: txn.First(TableACLBindingRules, "id", rule.ID) erroring while applying UpsertACLBindingRules via Raft — schema/index mismatch or corrupted state store.

Common situations: Version skew between servers; state store corruption; memdb internal errors.

Related errors


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

Appendix: source

Thrown at nomad/state/state_store_acl_binding_rule.go:87

	// update has the auth method detailed in binding rule. Therefore, check
	// again while in our write txn.
	if !allowMissingAuthMethod {
		method, err := s.GetACLAuthMethodByName(nil, rule.AuthMethod)
		if err != nil {
			return false, fmt.Errorf("ACL auth method lookup failed: %v", err)
		}
		if method == nil {
			return false, fmt.Errorf("ACL binding rule insert failed: ACL auth method not found")
		}
	}

	// This validation also happens within the RPC handler, but Raft latency
	// could mean that by the time the state call is invoked, another Raft
	// update has already written a method with the same name. We therefore
	// need to check we are not trying to create a rule with an existing ID.
	existingRaw, err := txn.First(TableACLBindingRules, indexID, rule.ID)
	if err != nil {
		return false, fmt.Errorf("ACL binding rule lookup failed: %v", err)
	}

	var existing *structs.ACLBindingRule
	if existingRaw != nil {
		existing = existingRaw.(*structs.ACLBindingRule)
	}

	// Depending on whether this is an initial create, or an update, we need to
	// check and set certain parameters. The most important is to ensure any
	// create index is carried over.
	if existing != nil {

		// If the rule already exists, check whether the update contains any
		// difference. If it doesn't, we can avoid a state update as well as
		// updates to any blocking queries.
		if existing.Equal(rule) {
			return false, nil
		}

View on GitHub (pinned to 482b49bf1a)