{"record":{"id":"63b0ed927a3cdd07","repo":"hashicorp/nomad","slug":"upserting-token-failed-v","errorCode":null,"errorMessage":"upserting token failed: %v","messagePattern":"upserting token failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/state/state_store.go","lineNumber":6405,"sourceCode":"\n\t\t// Update all the indexes\n\t\tif existing != nil {\n\t\t\texistTK := existing.(*structs.ACLToken)\n\t\t\ttoken.CreateIndex = existTK.CreateIndex\n\t\t\ttoken.ModifyIndex = index\n\n\t\t\t// Do not allow SecretID or create time to change\n\t\t\ttoken.SecretID = existTK.SecretID\n\t\t\ttoken.CreateTime = existTK.CreateTime\n\n\t\t} else {\n\t\t\ttoken.CreateIndex = index\n\t\t\ttoken.ModifyIndex = index\n\t\t}\n\n\t\t// Update the token\n\t\tif err := txn.Insert(\"acl_token\", token); err != nil {\n\t\t\treturn fmt.Errorf(\"upserting token failed: %v\", err)\n\t\t}\n\t}\n\n\t// Update the indexes table\n\tif err := txn.Insert(\"index\", &IndexEntry{\"acl_token\", index}); err != nil {\n\t\treturn fmt.Errorf(\"index update failed: %v\", err)\n\t}\n\treturn txn.Commit()\n}\n\n// DeleteACLTokens deletes the tokens with the given accessor ids\nfunc (s *StateStore) DeleteACLTokens(msgType structs.MessageType, index uint64, ids []string) error {\n\ttxn := s.db.WriteTxnMsgT(msgType, index)\n\tdefer txn.Abort()\n\n\t// Delete the tokens\n\tfor _, id := range ids {\n\t\tif _, err := txn.DeleteAll(\"acl_token\", \"id\", id); err != nil {","sourceCodeStart":6387,"sourceCodeEnd":6423,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/state/state_store.go#L6387-L6423","documentation":"Thrown when txn.Insert of an ACLToken into the 'acl_token' table fails during UpsertACLTokens. memdb Insert fails if the object is not of the registered table type or violates an index (e.g., missing required index fields), causing the whole transaction to abort.","triggerScenarios":"Inserting an *structs.ACLToken whose AccessorID or SecretID is empty/nil, breaking unique-index expectations; passing an object of the wrong type; schema registering different index fields than the token provides.","commonSituations":"Upserting tokens created manually (not via ACL API) with missing AccessorID/SecretID; a version change that added new required index fields; test harnesses constructing ACLToken literals.","solutions":["Ensure the ACLToken has non-empty AccessorID and SecretID and call token.SetHash() before upsert (as the store does when CreateTime is unset).","Construct tokens via the ACL token bootstrap/create API rather than manual structs.","Check that the binary and state schema versions match; inspect logs for the wrapped %v cause."],"exampleFix":"// before\ntoken := &structs.ACLToken{SecretID: secret}\ns.UpsertACLTokens(msgType, index, []*structs.ACLToken{token})\n// after\ntoken := &structs.ACLToken{AccessorID: accessor, SecretID: secret}\ntoken.SetHash()\ns.UpsertACLTokens(msgType, index, []*structs.ACLToken{token})","handlingStrategy":"validation","validationCode":"func validTokenForUpsert(t *structs.ACLToken) bool {\n    return t != nil && t.AccessorID != \"\" && t.SecretID != \"\"\n}\n// filter tokens before calling:\n// ok := filterSlice(tokens, validTokenForUpsert)","typeGuard":null,"tryCatchPattern":"if err := store.UpsertACLTokens(msgType, index, tokens); err != nil {\n    if strings.Contains(err.Error(), \"upserting token failed\") {\n        return fmt.Errorf(\"invalid ACLToken for acl_token table: %w\", err)\n    }\n    return err\n}","preventionTips":["Never upsert manually constructed tokens with empty AccessorID/SecretID","Use the ACL token create/bootstrap API to mint tokens","Call SetHash() and set CreateTime before upsert","Add unit tests covering token upsert with fully populated structs"],"tags":["nomad","state-store","acl","raft"],"backgroundTag":"state-store-write-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"}