通过 SSO 登录创建新用户时出现 Discourse DB 错误

摘要

由于没有账户的用户尝试通过 SSO 登录时生成了重复的键值,导致 Discourse 数据库约束错误。这会导致外部代理看到内部服务器错误(500)。

讨论

在 8 月 28 日或 29 日,我将 Discourse 更新到了最新的测试版(v2.4.0.beta2),并同时更新了所有已安装的 Discourse 插件。几乎在同一时间,我还更新了 SeAT,并重新配置 Discourse 以使用 UNIX socket,外部 Apache 可以代理/反向代理到该 socket。在此之前,人们可以通过 SeAT 的 EVE Online SSO 登录,如果他们没有账户,Discourse 会自动为他们创建新用户账户。

此后,没有任何新用户账户成功创建。相反,尝试登录的三个人都生成了如下错误:Failed to create or lookup user: ERROR: duplicate key value violates constraint "idx_category_users_user_id_category_id" DETAIL: Key (user_id, category_id)=(36, 6) already exists.category_id 始终为 6,但 user_id 在 33 到 44 之间变化,甚至出现重复的数字。

假设 category_id 指的是 categories 表中的条目,那么 6 似乎对应的是“Grass Clippings”(草屑)。假设 user_id 指的是 users 表中的条目,那么我们没有任何 ID 大于 32 的条目。

“Grass Clippings”这一类别至少对 2GTHRDiscourse2GTHRHighCouncilGRoLLake 组中的成员限制了阅读权限。至少有一位尝试连接的人的 add_groups 命令中包含了这三个组。第一个人尚未拥有这三个组中的任何一个,而中间的那个人至少拥有其中之一。他们都生成了相同类型的数据库错误,详细信息完全相同,除了 user_id 不同。

在升级之前通过 SSO 登录并创建 Discourse 账户的用户似乎没有遇到登录问题。

已尝试或查看的事项

  1. 关闭 force https 并恢复为外部 Apache 代理到 nginx 端口。
    不出所料,这没有任何效果。

  2. 调试和修复常见的 SSO 问题

  3. 注意 SSO 负载的双重 URL 编码

  4. 跟踪了回溯信息,看到 Discourse 执行到了 models/discourse_single_sign_on.rb 第 203 行的 match_email_or_create_user() 函数,该函数调用了 User.create!()。遗憾的是,参数等的日志记录发生在那之后,但由于处理停止并返回 HTTP 500 错误,代码从未到达那里。我检查了 shared/log/rails/production.log.* 以防万一。

其他评论

  • SeAT:虽然 SeAT Discourse 插件 没有更新,但 SeAT 的许多组件已更新。其中可能发生了变化。然而,错误显然发生在 Discourse 端,当尝试创建或查找不存在的用户时,因此我对问题出在 SeAT 端表示怀疑。

  • Discourse:我不记得升级前运行的是哪个 Discourse 测试版。我猜距离上次升级可能已经有一两个月了。

详细信息

错误
Failed to create or lookup user: ERROR:  duplicate key value violates unique constraint "idx_category_users_user_id_category_id"
DETAIL:  Key (user_id, category_id)=(36, 6) already exists.
.    add_groups: CORPBLUEP,2GTHRAllianceMember,2GTHRALL,2GTHRHighCouncil,2GTHRCorpDirector,2GTHROfficer,DoWCitadelGunner,HCDIM,CORPDIRBLUEP,2GTHRCorpRecruiter,CORPDIRLAWNS,CORPDIR123HC,GRoLLake,DoWCapital,DoWFax,User,CORPHRBLUEP,2GTHRDiscourse
admin: 
moderator: 
avatar_force_update: 
avatar_url: http://image.eveonline.com/Character/740426190_128.jpg
bio: 
card_background_url: 
email: something@somewhere.com
external_id: 740426190
groups: 
locale: 
locale_force_update: 
name: Mindframe
nonce: e6f9da9e62b720a1efd97348ca20f101
profile_background_url: 
remove_groups: Superuser,SPRKYAllianceMember,DoWFieldMarshall,DoWScoutCoordinator,DoWFCGang,DoWFCAlliance,DoWFCSenior,DoWScout,DoWSuper,DoWTitan,DoWFC,2GTHRCorpCEO,DoWTitanBridging,DoLLogisticsSov,DoLLogisticsShipping,HCDoW,HCDoL,HCDoC,HCDoF,DoCDoIT,DoCTechnoMage,DoCDiplomat,DoCDepartmentLead,DoCRecruiterPilots,DoCRecruiterCorporations,DoCDiplomatLead,DoWBLOP,ViewGroups,CORPAIEU,CORPDIRAIEU,CORPZBMC,CORPC.R.Y,CORP123HC,CORPALTBH,CORPLAWNS,CORPDIRZBMC,CORPDIRC.R.Y,CORPDIRALTBH,CORPF3R4L,CORPDIRF3R4L,CORPSPRKY,CORPDIRSPRKY,CORPRMKR,CORPDIRRMKR,CORPHR123HC,CORPHRAIEU,CORPHRZBMC,CORPHRC.R.Y,CORPHRF3R4L,SPRKYDiscourse,CORPHRLAWNS,CORPDIROUSYN,CORPHROUSYN,CORPOUSYN,DoWReimbursementTeam,DoWCarrier,DoWDread,WCMember,WCALL,WCMindframesMarketVisitors
require_activation: 
return_sso_url: 
suppress_welcome_message: 
title: 
username: Mindframe
website:     /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/patches/db/pg.rb:110:in `async_exec'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/patches/db/pg.rb:110:in `async_exec'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/mini_sql-0.2.2/lib/mini_sql/postgres/connection.rb:118:in `run'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/mini_sql-0.2.2/lib/mini_sql/postgres/connection.rb:90:in `exec'
/var/www/discourse/app/models/user.rb:1403:in `set_default_categories_preferences'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:426:in `block in make_lambda'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:236:in `block in halting_and_conditional'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:517:in `block in invoke_after'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:517:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:517:in `invoke_after'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:133:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:816:in `_run_create_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/callbacks.rb:346:in `_create_record'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/timestamp.rb:102:in `_create_record'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/persistence.rb:705:in `create_or_update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/callbacks.rb:342:in `block in create_or_update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:132:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:816:in `_run_save_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/callbacks.rb:342:in `create_or_update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/persistence.rb:308:in `save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/validations.rb:52:in `save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:315:in `block in save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:387:in `block in with_transaction_returning_status'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:267:in `block in transaction'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:239:in `block in within_new_transaction'
/usr/local/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:236:in `within_new_transaction'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:267:in `transaction'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:212:in `transaction'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:385:in `with_transaction_returning_status'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:315:in `save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/suppressor.rb:48:in `save!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/persistence.rb:53:in `create!'
/var/www/discourse/app/models/discourse_single_sign_on.rb:203:in `block in match_email_or_create_user'
/var/www/discourse/lib/distributed_mutex.rb:31:in `block in synchronize'
/var/www/discourse/lib/distributed_mutex.rb:27:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:27:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:12:in `synchronize'
/var/www/discourse/app/models/discourse_single_sign_on.rb:186:in `match_email_or_create_user'
/var/www/discourse/app/models/discourse_single_sign_on.rb:74:in `lookup_or_create_user'
/var/www/discourse/app/controllers/session_controller.rb:169:in `sso_login'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/base.rb:194:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/rendering.rb:30:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:42:in `block in process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:132:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:41:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/rescue.rb:22:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in `block in instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in `instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:32:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/railties/controller_runtime.rb:24:in `process_action'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/base.rb:134:in `process'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionview-5.2.3/lib/action_view/rendering.rb:32:in `process'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/mini_profiler/profiling_methods.rb:78:in `block in profile_method'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:191:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:252:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:34:in `serve'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:52:in `block in serve'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in `serve'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:840:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-protection-2.0.7/lib/rack/protection/frame_options.rb:31:in `call'
/var/www/discourse/lib/middleware/omniauth_bypass_middleware.rb:68:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/tempfile_reaper.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/conditional_get.rb:25:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/head.rb:12:in `call'
/var/www/discourse/lib/content_security_policy/middleware.rb:12:in `call'
/var/www/discourse/lib/middleware/anonymous_cache.rb:219:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:232:in `context'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:226:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/cookies.rb:670:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:98:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/middleware/reporter.rb:43:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:38:in `call_app'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:28:in `call'
/var/www/discourse/config/initializers/100-quiet_logger.rb:18:in `call'
/var/www/discourse/config/initializers/100-silence_logger.rb:31:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/request_id.rb:27:in `call'
/var/www/discourse/lib/middleware/enforce_hostname.rb:17:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/method_override.rb:22:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:14:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/sendfile.rb:111:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/mini_profiler/profiler.rb:171:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/message_bus-2.2.2/lib/message_bus/rack/middleware.rb:57:in `call'
/var/www/discourse/lib/middleware/request_tracker.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/engine.rb:524:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `public_send'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `method_missing'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:68:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:605:in `process_client'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:700:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:548:in `spawn_missing_workers'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:144:in `start'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/bin/unicorn:128:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `<main>'
3 个赞

这与以下代码有关:

这里发生的情况是,我们按如下方式修改了 category_user 的索引:

您的站点设置中是否存在一个同时被设置为“默认关注”和“默认追踪”的群组?

请查看:default categories watchingdefault categories trackingdefault categories muted 以及 default categories watching first post

以下修复可以解决问题:

diff --git a/app/models/user.rb b/app/models/user.rb
index c1a94949a6..85b2ca9244 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1390,10 +1390,15 @@ class User < ActiveRecord::Base
     return if self.staged?
 
     values = []
+    # 稍后分配集合
+    seen = nil
 
     %w{watching watching_first_post tracking muted}.each do |s|
       category_ids = SiteSetting.get("default_categories_#{s}").split("|").map(&:to_i)
       category_ids.each do |category_id|
+        seen ||= Set.new
+        next if seen.include?(category_id)
+        seen << category_id
         next if category_id == 0
         values << "(#{self.id}, #{category_id}, #{CategoryUser.notification_levels[s.to_sym]})"
       end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index cc50d88b2e..4075ee6194 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1603,8 +1603,12 @@ describe User do
 
       SiteSetting.default_categories_watching = category0.id.to_s
       SiteSetting.default_categories_tracking = category1.id.to_s
-      SiteSetting.default_categories_muted = category2.id.to_s
+
+      # 这是无效的,但我们不进行验证,因此确保不会导致任何故障
+      SiteSetting.default_categories_muted = "#{category2.id}|#{category0.id}"
+
       SiteSetting.default_categories_watching_first_post = category3.id.to_s
+
     end
 
     it "has overriden preferences" do

但我并不喜欢这个修复方案。站点设置应在保存时验证是否存在重叠,并且我们应该迁移掉错误的数据。

@Daniel 我认为你在这里引入了新的约束,也许可以在用户设置站点设置时跟进添加一个验证?

3 个赞

我有被跟踪的分类和被关注的分类,但它们之间没有重叠。它们都是顶级分类。不过,我在“默认关注分类”和“默认关注首帖分类”之间存在重叠。某个分类同时出现在这两者中,而该分类的 ID 与我数据库中约束错误所提及的分类 ID 一致。这会不会是问题的一部分?

回复自己:将该分类从“默认关注首帖分类”中移除,使其仅存在于“默认关注分类”中,问题得以解决;此前无法登录的未注册用户现在可以正常登录了。

3 个赞

我刚刚遇到了这个错误。

用户无法登录,因为“招聘备注”和“合作伙伴备注”在 default categories regular 中重复了。

1 个赞

在保存设置时,应非常容易防止重复。不过,修复历史记录的问题还不确定。

@vinothkannans 能否确保在保存时,这些默认设置能清理以下内容?

  • 移除重复项
  • 如果您正在为类别 A 保存“默认观看”设置,而类别 A 的“默认追踪”已设置,则报错并说明问题
1 个赞

我对这种情况发生的原因的最佳推测是:

  1. 创建了“合作伙伴备注”作为独立类别,并将其设置为“默认类别常规”。
  2. 创建了“招聘备注”作为独立类别,并将其设置为“默认类别常规”。
  3. 创建了“组织者”作为独立类别,并将其设置为“默认类别常规”。
  4. 更改了“合作伙伴备注”和“招聘备注”的设置,将其父类别设为“组织者”,并且(我认为)没有对“默认类别常规”设置进行任何更改。

我完全支持修复此错误,因为新用户无法注册将导致灾难性后果,且难以察觉,因为新用户很可能会直接放弃,而不会联系任何人寻求帮助。

在此期间,或许错误消息中可以包含:“如果您在注册过程中继续遇到问题,请联系 site email 寻求支持?”

1 个赞