hashicorp/nomad · error

policy lookup failed: %v

Error message

policy lookup failed: %v

What it means

Thrown during UpsertACLPolicies when the lookup of an existing ACL policy by name (txn.First("acl_policy", "id", policy.Name)) returns an error. The upsert needs the existing row to preserve CreateIndex; if the lookup itself fails the whole policy upsert transaction is aborted.

Source

Thrown at nomad/state/state_store.go:6259

	return nil
}

// UpsertACLPolicies is used to create or update a set of ACL policies
func (s *StateStore) UpsertACLPolicies(msgType structs.MessageType, index uint64, policies []*structs.ACLPolicy) error {
	txn := s.db.WriteTxnMsgT(msgType, index)
	defer txn.Abort()

	for _, policy := range policies {
		// Ensure the policy hash is non-nil. This should be done outside the state store
		// for performance reasons, but we check here for defense in depth.
		if len(policy.Hash) == 0 {
			policy.SetHash()
		}

		// Check if the policy already exists
		existing, err := txn.First("acl_policy", "id", policy.Name)
		if err != nil {
			return fmt.Errorf("policy lookup failed: %v", err)
		}

		// Update all the indexes
		if existing != nil {
			policy.CreateIndex = existing.(*structs.ACLPolicy).CreateIndex
			policy.ModifyIndex = index
		} else {
			policy.CreateIndex = index
			policy.ModifyIndex = index
		}

		// Update the policy
		if err := txn.Insert("acl_policy", policy); err != nil {
			return fmt.Errorf("upserting policy failed: %v", err)
		}
	}

	// Update the indexes tabl

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Retry the ACL policy create/update request
  2. Check server logs for memdb or restore-related errors preceding this message
  3. Restore the Nomad server from a consistent snapshot if the state store is corrupt
  4. Upgrade Nomad if a version-specific memdb bug is suspected
Defensive patterns

Strategy: retry

Validate before calling

// Ensure the policy name is valid before upserting (Nomad ACL policy names)
function isValidPolicyName(name) {
  return typeof name === 'string' && /^[a-zA-Z0-9-]{1,128}$/.test(name);
}

Type guard

function isACLPolicyArg(p) {
  return p && typeof p.Name === 'string' && p.Name.length > 0 && typeof p.Rules === 'string';
}

Try / catch

try {
  await nomad.post('/v1/acl/policies', policies);
} catch (e) {
  if (String(e).includes('policy lookup failed')) {
    checkServerHealth();
    return retryWithBackoff(() => nomad.post('/v1/acl/policies', policies));
  }
  throw e;
}

Prevention

When it happens

Trigger: UpsertACLPolicies is called (e.g. via ACL policy create/update API or state restore) and the memdb First query on the acl_policy table errors — internal memdb failure rather than a not-found result (not-found returns existing == nil).

Common situations: Corrupted ACL policy table after partial restore; go-memdb internal errors under memory pressure; rare races during state store restore while writes are in flight.

Related errors


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