{"record":{"id":"a75d9ebda016745e","repo":"hashicorp/nomad","slug":"policy-lookup-failed-v","errorCode":null,"errorMessage":"policy lookup failed: %v","messagePattern":"policy lookup failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/state/state_store.go","lineNumber":6259,"sourceCode":"\treturn nil\n}\n\n// UpsertACLPolicies is used to create or update a set of ACL policies\nfunc (s *StateStore) UpsertACLPolicies(msgType structs.MessageType, index uint64, policies []*structs.ACLPolicy) error {\n\ttxn := s.db.WriteTxnMsgT(msgType, index)\n\tdefer txn.Abort()\n\n\tfor _, policy := range policies {\n\t\t// Ensure the policy hash is non-nil. This should be done outside the state store\n\t\t// for performance reasons, but we check here for defense in depth.\n\t\tif len(policy.Hash) == 0 {\n\t\t\tpolicy.SetHash()\n\t\t}\n\n\t\t// Check if the policy already exists\n\t\texisting, err := txn.First(\"acl_policy\", \"id\", policy.Name)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"policy lookup failed: %v\", err)\n\t\t}\n\n\t\t// Update all the indexes\n\t\tif existing != nil {\n\t\t\tpolicy.CreateIndex = existing.(*structs.ACLPolicy).CreateIndex\n\t\t\tpolicy.ModifyIndex = index\n\t\t} else {\n\t\t\tpolicy.CreateIndex = index\n\t\t\tpolicy.ModifyIndex = index\n\t\t}\n\n\t\t// Update the policy\n\t\tif err := txn.Insert(\"acl_policy\", policy); err != nil {\n\t\t\treturn fmt.Errorf(\"upserting policy failed: %v\", err)\n\t\t}\n\t}\n\n\t// Update the indexes tabl","sourceCodeStart":6241,"sourceCodeEnd":6277,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/state/state_store.go#L6241-L6277","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Retry the ACL policy create/update request","Check server logs for memdb or restore-related errors preceding this message","Restore the Nomad server from a consistent snapshot if the state store is corrupt","Upgrade Nomad if a version-specific memdb bug is suspected"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Ensure the policy name is valid before upserting (Nomad ACL policy names)\nfunction isValidPolicyName(name) {\n  return typeof name === 'string' && /^[a-zA-Z0-9-]{1,128}$/.test(name);\n}","typeGuard":"function isACLPolicyArg(p) {\n  return p && typeof p.Name === 'string' && p.Name.length > 0 && typeof p.Rules === 'string';\n}","tryCatchPattern":"try {\n  await nomad.post('/v1/acl/policies', policies);\n} catch (e) {\n  if (String(e).includes('policy lookup failed')) {\n    checkServerHealth();\n    return retryWithBackoff(() => nomad.post('/v1/acl/policies', policies));\n  }\n  throw e;\n}","preventionTips":["Retry idempotent policy upserts; they are safe to repeat","Keep servers memory-healthy; memdb failures are usually resource-related","Restore only from consistent snapshots","Validate policy names/rules with nomad acl policy check before applying in bulk"],"tags":["nomad","acl","state-store","memdb"],"backgroundTag":"acl-policy-lookup-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}