Зависание Git и ошибка Oops на странице ошибок для аккаунтов администраторов и модераторов

ActionView::Template::Error (no implicit conversion of Array into String)

Я воспроизвёл проблему с ошибкой на странице «Oops» при входе, которая, похоже, затрагивает только администраторов, а в некоторых случаях и другие учётные записи персонала. В данном случае это учётная запись администратора, но только те администраторы, которые были созданы до «git hang». Ошибка возникает при попытке повторного входа.

Затем я проверил логи, теперь я лучше знаком с тем, как работает вывод в /logs, и это отличная функция!

Эта ошибка отображается как «критическая ошибка» (fatal error), она началась 22-го числа и очень похожа на проблему «git hang», но в данном случае она остаётся нерешённой, несмотря на многочисленные пересборки до настоящего момента. Это означает, что некоторые учётные записи администраторов фактически заблокированы. Пожалуйста, ознакомьтесь с информацией и логами backtrace ниже:

Информация

Message

ActionView::Template::Error (no implicit conversion of Array into String)
app/serializers/current_user_serializer.rb:216:in 'CurrentUserSerializer#has_new_upcoming_changes'
lib/application_layout_preloader.rb:81:in 'ApplicationLayoutPreloader#preload_current_user_data'
lib/application_layout_preloader.rb:32:in 'ApplicationLayoutPreloader#preloaded_data'
app/helpers/application_helper.rb:987:in 'ApplicationHelper#preloaded_json'
app/views/layouts/application.html.erb:111
lib/topic_list_responder.rb:16:in 'block (2 levels) in TopicListResponder#respond_with_list'
lib/topic_list_responder.rb:7:in 'TopicListResponder#respond_with_list'
app/controllers/list_controller.rb:119:in 'block (2 levels) in class:ListController'
app/controllers/application_controller.rb:458:in 'block in ApplicationController#with_resolved_locale'
app/controllers/application_controller.rb:458:in 'ApplicationController#with_resolved_locale'
app/controllers/application_controller.rb:1140:in 'ApplicationController#ensure_dont_cache_page'
lib/middleware/omniauth_bypass_middleware.rb:35:in 'Middleware::OmniauthBypassMiddleware#call'
lib/middleware/crawler_hooks.rb:13:in 'Middleware::CrawlerHooks#call'
lib/content_security_policy/middleware.rb:12:in 'ContentSecurityPolicy::Middleware#call'
lib/middleware/anonymous_cache.rb:431:in 'Middleware::AnonymousCache#call'
lib/middleware/csp_script_nonce_injector.rb:13:in 'Middleware::CspScriptNonceInjector#call'
lib/middleware/track_view_session_id_injector.rb:12:in 'Middleware::TrackViewSessionIdInjector#call'
config/initializers/008-rack-cors.rb:14:in 'Discourse::Cors#call'
lib/middleware/default_headers.rb:13:in 'Middleware::DefaultHeaders#call'
config/initializers/100-quiet_logger.rb:20:in 'DiscourseRackQuietAssetsLogger#call'
config/initializers/100-silence_logger.rb:29:in 'SilenceLogger#call'
lib/middleware/enforce_hostname.rb:23:in 'Middleware::EnforceHostname#call'
lib/middleware/request_tracker.rb:384:in 'Middleware::RequestTracker#call'
lib/middlewar...

Backtrace:


Backtrace

activesupport (8.1.4) lib/active_support/values/time_zone.rb:461:in 'Date._parse'
activesupport (8.1.4) lib/active_support/values/time_zone.rb:461:in 'ActiveSupport::TimeZone#parse'
app/serializers/current_user_serializer.rb:216:in 'CurrentUserSerializer#has_new_upcoming_changes'
(eval at active_model_serializers-0.8.4/lib/active_model/serializer.rb:467):81:in 'CurrentUserSerializer#_fast_attributes'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:456:in 'ActiveModel::Serializer#attributes'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:480:in 'ActiveModel::Serializer#_serializable_hash'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:359:in 'ActiveModel::Serializer#serializable_hash'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:347:in 'ActiveModel::Serializer#as_json'
activesupport (8.1.4) lib/active_support/json/encoding.rb:53:in 'Oj::Rails::Encoder#encode'
activesupport (8.1.4) lib/active_support/json/encoding.rb:53:in 'ActiveSupport::JSON.encode'
activesupport (8.1.4) lib/active_support/core_ext/object/json.rb:42:in 'ActiveSupport::ToJsonWithActiveSupportEncoder#to_json'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:331:in 'ActiveModel::Serializer#to_json'
multi_json (1.21.1) lib/multi_json/adapters/oj.rb:67:in 'Oj.dump'
multi_json (1.21.1) lib/multi_json/adapters/oj.rb:67:in 'MultiJSON::Adapters::Oj#dump'
multi_json (1.21.1) lib/multi_json/adapter.rb:110:in 'MultiJSON::Adapter.dump'
multi_json (1.21.1) lib/multi_json.rb:215:in 'MultiJSON.generate'
multi_json (1.21.1) lib/multi_json/deprecated.rb:34:in 'Kernel#public_send'
multi_json (1.21.1) lib/multi_json/deprecated.rb:34:in 'block in MultiJSON.deprecate_alias'
multi_json (1.21.1) lib/multi_json.rb:298:in 'Kernel#public_send'
multi_json (1.21.1) lib/multi_json.rb:298:in 'block (2 levels) in module:MultiJson'
lib/application_layout_preloader.rb:81:in 'ApplicationLayoutPreloader#preload_current_user_data'
lib/application_layout_preloader.rb:32:in 'ApplicationLayoutPreloader#preloaded_data'
app/helpers/application_helper.rb:987:in 'ApplicationHelper#preloaded_json'
app/views/layouts/application.html.erb:111
actionview (8.1.4) lib/action_view/base.rb:281:in 'Kernel#public_send'
actionview (8.1.4) lib/action_view/base.rb:281:in 'ActionView::Base#_run'
actionview (8.1.4) lib/action_view/template.rb:284:in 'block in ActionView::Template#render'
activesupport (8.1.4) lib/active_support/notifications.rb:212:in 'ActiveSupport::Notifications.instrument'
actionview (8.1.4) lib/action_view/template.rb:590:in 'ActionView::Template#instrument_render_template'
actionview (8.1.4) lib/action_view/template.rb:272:in 'ActionView::Template#render'
rack-mini-profiler (5.0.0) lib/mini_profiler/profiling_methods.rb:90:in 'block in ActionView::Template#profile_method'
actionview (8.1.4) lib/action_view/renderer/template_renderer.rb:77:in 'block in ActionView::TemplateRenderer#render_with_layout'
activesupport (8.1.4) lib/active_support/notifications.rb:210:in 'block in ActiveSupport::Notifications.instrument'
activesupport (8.1.4) lib/active_support/notifications/instrumenter.rb:58:in 'ActiveSupport::Notifications::Instrumenter#instrument'
activesupport (8.1.4) lib/active_support/notifications.rb:210:in 'ActiveSupport::Notifications.instrument'
actionview (8.1.4) lib/action_view/renderer/template_renderer.rb:75:in 'ActionView::TemplateRenderer#render_with_layout'
actionview (8.1.4) lib/action_view/renderer/template_renderer.rb:59:in 'ActionView::TemplateRenderer#render_template'
actionview (8.1.4) lib/action_view/renderer/template_renderer.rb:11:in 'ActionView::TemplateRenderer#render'
actionview (8.1.4) lib/action_view/renderer/renderer.rb:58:in 'ActionView::Renderer#render_template_to_object'
actionview (8.1.4) lib/action_view/renderer/renderer.rb:31:in 'ActionView::Renderer#render_to_object'
actionview (8.1.4) lib/action_view/rendering.rb:136:in 'block in ActionView::Rendering#_render_template'
actionview (8.1.4) lib/action_view/base.rb:308:in 'ActionView::Base#in_rendering_context'
actionview (8.1.4) lib/action_view/rendering.rb:135:in 'ActionView::Rendering#_render_template'
actionpack (8.1.4) lib/action_controller/metal/streaming.rb:179:in 'ActionController::Streaming#_render_template'
actionview (8.1.4) lib/action_view/rendering.rb:122:in 'ActionView::Rendering#render_to_body'
actionpack (8.1.4) lib/action_controller/metal/rendering.rb:192:in 'ActionController::Rendering#render_to_body'
actionpack (8.1.4) lib/action_controller/metal/renderers.rb:155:in 'ActionController::Renderers#render_to_body'
actionpack (8.1.4) lib/abstract_controller/rendering.rb:28:in 'AbstractController::Rendering#render'
actionpack (8.1.4) lib/action_controller/metal/rendering.rb:173:in 'ActionController::Rendering#render'
actionpack (8.1.4) lib/action_controller/metal/instrumentation.rb:31:in 'block (2 levels) in ActionController::Instrumentation#render'
activesupport (8.1.4) lib/active_support/benchmark.rb:17:in 'ActiveSupport::Benchmark.realtime'
actionpack (8.1.4) lib/action_controller/metal/instrumentation.rb:31:in 'block in ActionController::Instrumentation#render'
actionpack (8.1.4) lib/action_controller/metal/instrumentation.rb:100:in 'ActionController::Instrumentation#cleanup_view_runtime'
activerecord (8.1.4) lib/active_record/railties/controller_runtime.rb:48:in 'ActiveRecord::Railties::ControllerRuntime#cleanup_view_runtime'
actionpack (8.1.4) lib/action_controller/metal/instrumentation.rb:30:in 'ActionController::Instrumentation#render'
lib/topic_list_responder.rb:16:in 'block (2 levels) in TopicListResponder#respond_with_list'
actionpack (8.1.4) lib/action_controller/metal/mime_responds.rb:224:in 'ActionController::MimeResponds#respond_to'
lib/topic_list_responder.rb:7:in 'TopicListResponder#respond_with_list'
app/controllers/list_controller.rb:119:in 'block (2 levels) in class:ListController'
actionpack (8.1.4) lib/action_controller/metal/basic_implicit_render.rb:8:in 'ActionController::BasicImplicitRender#send_action'
actionpack (8.1.4) lib/abstract_controller/base.rb:221:in 'AbstractController::Base#process_action'
actionpack (8.1.4) lib/action_controller/metal/rendering.rb:199:in 'ActionController::Rendering#process_action'
actionpack (8.1.4) lib/abstract_controller/callbacks.rb:267:in 'block in AbstractController::Callbacks#process_action'
activesupport (8.1.4) lib/active_support/callbacks.rb:121:in 'block in ActiveSupport::Callbacks#run_callbacks'
app/controllers/application_controller.rb:458:in 'block in ApplicationController#with_resolved_locale'
i18n (1.14.8) lib/i18n.rb:354:in 'I18n::Base#with_locale'
app/controllers/application_controller.rb:458:in 'ApplicationController#with_resolved_locale'
activesupport (8.1.4) lib/active_support/callbacks.rb:130:in 'block in ActiveSupport::Callbacks#run_callbacks'
app/controllers/application_controller.rb:1140:in 'ApplicationController#ensure_dont_cache_page'
activesupport (8.1.4) lib/active_support/callbacks.rb:130:in 'block in ActiveSupport::Callbacks#run_callbacks'
activesupport (8.1.4) lib/active_support/callbacks.rb:141:in 'ActiveSupport::Callbacks#run_callbacks'
actionpack (8.1.4) lib/abstract_controller/callbacks.rb:266:in 'AbstractController::Callbacks#process_action'
actionpack (8.1.4) lib/action_controller/metal/rescue.rb:36:in 'ActionController::Rescue#process_action'
actionpack (8.1.4) lib/action_controller/metal/instrumentation.rb:76:in 'block in ActionController::Instrumentation#process_action'
activesupport (8.1.4) lib/active_support/notifications.rb:210:in 'block in ActiveSupport::Notifications.instrument'
activesupport (8.1.4) lib/ac

Для тех, кто оказался в подобной ситуации, рабочим обходным решением, которое позволило получить доступ администратора к экземпляру Discourse, было создание новой учётной записи администратора с помощью команды rake create:admin после входа в приложение через ./launcher enter app.

Однако это не решает проблему окончательно: существующие учётные записи администраторов по-прежнему получают страницу ошибки «Oops» и не могут войти в систему как обычно.

Надеюсь, что в какой-то момент появится исправление для этой проблемы. Заранее благодарю за любые идеи или советы.


Возможно, связанные темы:

В попытке найти нестандартное решение с использованием стандартных функций Discourse, я задумался, можно ли объединить аккаунты пользователей. Например, создать новый аккаунт администратора, а затем объединить его со старым аккаунтом администратора (для персонала это нужно делать через консоль).

Другая идея состояла в том, чтобы отозвать, а затем снова выдать статус администратора, но я не знаю, может ли отзыв статуса что-то сломать.

Это скорее спонтанная догадка с моей стороны. Я не пытался ничего из вышеперечисленного, но я поигрался с созданием темы, а затем сменой её владельца на аккаунт администратора, заблокированный из-за ошибки, и тогда в этом Discourse появилось уведомление post-notice new-user со следующим текстом:

:tada: Это первый пост [имя пользователя] — давайте поприветствуем его на сайте!

О боже, это так, будто администратора не существовало вплоть до момента смены владельца в этом посте.

Может ли это указывать на что-то конкретное? :thinking:

Я не обращал на это внимания, так как это были всего лишь «предупреждения», но одновременно возникает ошибка MaxMindDB, которая предшествует описанной выше ошибке ActiveVIEW::Tempalte::Error.

MaxMindDB (/var/www/discourse/vendor/data/GeoLite2-City.mmdb) could not be found: No such file or directory @ rb_sysopen - /var/www/discourse/vendor/data/GeoLite2-City.mmdb
MaxMindDB (/var/www/discourse/vendor/data/GeoLite2-ASN.mmdb) could not be found: No such file or directory @ rb_sysopen - /var/www/discourse/vendor/data/GeoLite2-ASN.mmdb

На вкладке ENV я заметил

Jobs::SuspiciousLogin

Возможно, эта не фатальная ошибка MaxMindDB (которая является предупреждением) блокирует вход для пользователя Admin и по какой-то причине вызывает страницу Oops, или это часть бага?

Это случай некорректной настройки maxmind?

Доступ к файлам Maxmind заблокирован в некоторых регионах. Я лично сталкивался с этим в Китае.

Спасибо. Однако этот сервер Discourse не находится в Китае, и администратор, пытающийся подключиться, тоже не из Китая. К тому же я не думаю, что MaxMindDB вообще был настроен, или, если он был настроен частично, то настройка так и не была завершена.

Я смутно помню настройки MaxMindDB в админке, но сейчас ничего не могу найти.

Кроме того, я только что кое-что понял: чтобы видеть /logs, нужно быть вошедшим в систему как администратор. Значит, соответствующий администратор может просматривать логи, а оттуда перейти на /admin через ссылку «вернуться на сайт», но при этом сталкивается с пульсирующими орбами НЛО (5 синими кругами). То есть он проходит хотя бы мимо страницы Oops, пусть и окольным путём, но всё равно не попадает внутрь. :thinking:

Я вижу в логах, что эта окольная активность порождает всё больше ошибок, описанных в первом сообщении.

ActionView::Template::Error (no implicit conversion of Array into String)

вызов исходит с сервера, место установки соединения не имеет значения — стоит проверить

Хорошо, но сервер не находится в Китае.

это был просто пример.

Ох, да, конечно.. ох! :grin: Просто не уверен, что мне стоит проверять в данном случае.

@merefield @Ed_S @Falco единственный пример этой ошибки, который я могу найти и который похож, — вот здесь Error "no implicit conversion of Array into String" when using Gemini AI analysis on posts with images Возможно, мне следовало опубликовать эту тему в разделе Contribute > Bug?

Похоже, это связано с отображением предстоящих изменений — видеть это могут только администраторы. Согласно ask.discourse.com

Вся функция управляется скрытым параметром сайта enable_upcoming_changes, который устанавливается в false в консоли Rails:

SiteSetting.enable_upcoming_changes = false

Однако для этого требуется доступ к терминалу/серверу, поэтому это возможно только при самостоятельном хостинге.

Спасибо, я выполнил эту команду в консоли Rails, но она сообщила «команда не найдена» :thinking:

ок, извини, оказалось, что LLM дал мне устаревшую информацию.

вот несколько команд, которые я пробовал и использовал.

вывести список администраторов и значение их настройки для предстоящих изменений в виде таблицы:

# docker exec -it app rails r 'User.where(admin: true).each { |u| puts "#{u.id} #{u.username} #{u.user_option.enable_upcoming_change_available_notifications}" }'
-1 system true
-2 discobot true
1 AdminTeam false

для заданного id — в моем случае 1 — переключить настройку для этого id:

# docker exec -it app rails r 'x=1;User.find(x).user_option.update!(enable_upcoming_change_available_notifications: !User.find(x).user_option.enable_upcoming_change_available_notifications)'

я скорее предпочитаю однострочник из корневой оболочки, хотя, конечно, можно зайти в docker, затем в rails и выполнять действия, если так удобнее.

У меня всегда немного дезориентация, поэтому под root shell вы имеете в виду запуск через ./launcher enter app и rails c?

Хорошо, вот вывод:

-1 system true

Ни старые, ни новые администраторы, ни discobot, ни кто-либо другой не отображаются в списке.

Возможно, в этом и заключается проблема: нужно, чтобы эта настройка была применена или включена для конкретного администратора. Если это так, как найти его ID?

Хорошо, я снова выполнил команду и нашёл id — это 1, то есть та же самая конфигурация.

Однако, когда я ввожу команду ниже и запускаю её, выводится => true.

x=1;User.find(x).user_option.update!(enable_upcoming_change_available_notifications: !User.find(x).user_option.enable_upcoming_change_available_notifications)

Мы хотим, чтобы значение было false, верно? Поэтому я не вижу, что нужно изменить в этой команде. Я понимаю действие как «найти» и ничего больше. Вывод => true, что, конечно, не соответствует целевому пользователю.

Наверное, мне стоило выбрать более простой подход…

# docker exec -it app rails r 'x=1;User.find(x).user_option.update!(enable_upcoming_change_available_notifications: false)'

и так далее. Не понимаю, почему я не подумал об этом.

Я в приложении и в rails c, вставляю это, и оно выводит

=> true

Однако я проверил, и в табличном выводе оно действительно переключилось на false.

Я попробовал войти в систему, но всё равно получаю ошибку. Возможно, мне нужно пересобрать проект?

Позвольте мне вернуться к предыдущему… То, что я делал там, было попыткой изменить настройки администратора в надежде, что код, вызывающий исключение, не потребуется запускать.

Но на самом деле нам нужно выяснить, есть ли ошибка в коде, которую необходимо исправить, или что-то странное в вашей базе данных, чего там быть не должно. Или, возможно, и то и другое.

Стек вызовов (backtrace) указывает на этот код в app/serializers/current_user_serializer.rb

  def has_new_upcoming_changes
    last_visited = object.custom_fields["last_visited_upcoming_changes_at"]
    return false if last_visited.blank? && object.created_at < Discourse.site_creation_date + 1.hour
    cutoff = last_visited.present? ? Time.zone.parse(last_visited) : object.created_at
    UpcomingChangeEvent.added.not_backfilled.where("created_at > ?", cutoff).exists?
  end

Можно выполнить запрос через Data Explorer, чтобы посмотреть, какое значение last_visited_upcoming_changes_at имеют ваши учетные записи администраторов.

SELECT 
    ucf.id AS custom_field_id, 
    ucf.user_id, 
    u.username,
    ucf.name, 
    ucf.value 
FROM user_custom_fields ucf
INNER JOIN users u ON u.id = ucf.user_id
WHERE ucf.name = 'last_visited_upcoming_changes_at'
  AND u.admin = true

и это может дать результат. В моем случае (недавно обновился до v2026.7.3) это просто строка с датой, и, я думаю, так и должно быть.

Спасибо, теперь возвращается два кастомных поля для того же старого администратора, но оба записи имеют одинаковое значение времени:

| last_visited_upcoming_changes_at | 2026-09-22T10:30:47Z |
| last_visited_upcoming_changes_at | 2026-09-22T10:30:47Z |

В то время как новый аккаунт администратора показывает более актуальную метку времени, при этом для этого пользователя есть только одна запись кастомного поля.

| last_visited_upcoming_changes_at | 2026-10-02T08:23:22Z |


Текущая версия Discourse: 2026.10.0-latest