Git 중단 및 관리자/모더레이터 계정 오류 페이지 문제

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

관리자 계정 및 일부 경우 다른 스태프 계정에만 영향을 미치는 것으로 보이는 로그인 Oops Page 오류 문제를 재현했습니다. 이번에는 관리자 계정에서 발생했으며, 단순히 다른 로그인을 시도함으로써 “git hang” 이전의 관리자 계정에서만 발생하는 것을 확인했습니다.

이제 /logs 출력 기능이 어떻게 작동하는지에 대해 더 익숙해지면서 로그를 확인해 보았는데, 정말 훌륭합니다!

이 오류는 "fatal error"로 표시되며 22일에 시작되었고 “git hang” 문제와 매우 유사해 보입니다. 그러나 이번 경우 여러 번의 재빌드에도 불구하고 아직까지 해결되지 않아 일부 관리자 계정이 사실상 잠겨 있는 상태입니다. 아래 정보와 백트레이스 로그를 확인해 주세요:

정보

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

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 인스턴스에 접근할 수 있도록 허용한 작동하는 우회 방법은 ./launcher enter app를 통해 앱에 진입한 후 rake create:admin 명령을 사용하여 관리자 사용자 계정을 새로 만드는 것이었습니다.

그러나 이는 근본적인 문제를 해결하지는 않으며, 기존 관리자 계정은 여전히 Oops Error 페이지를 보고 정상적으로 로그인할 수 없습니다.

이 문제에 대한 수정이 언젠가 이루어지기를 바라며, 미리 통찰이나 팁을 주시면 감사하겠습니다.


관련 주제 가능:

표준 Discourse 기능을 활용하여 해결책을 찾아보려다, ‘merge’ 사용자 계정이 작동할지 궁금해졌습니다. 예를 들어, 새로운 관리자 계정을 생성한 다음 기존 관리자 계정에 병합하는 방식입니다(스태프의 경우 콘솔을 통해 수행해야 합니다).

다른 아이디어는 관리자 권한을 박탈한 후 다시 부여하는 것이었지만, 권한 박탈이 문제를 일으킬지 확실하지 않습니다.

이것은 제 나름의 즉흥적인 시도이며, 위 방법들을 실제로 시도해 보지는 않았습니다. 다만, 게시물을 작성한 후 소유권을 오류로 인해 잠금 해제된 관리자 계정으로 변경해 보았더니, 이 Discourse의 post-notice new-user 알림이 다음과 같이 표시되었습니다:

:tada: [user name] 님이 처음으로 게시물을 작성했습니다 — 사이트에 오신 것을 환영하세요!

아니, 소유권 변경 게시물 시점까지 관리자 사용자가 존재하지 않았던 것처럼 보입니다.

이것이 무언가를 시사하는 것일까요? :thinking:

해당 경고들은 단순히 "경고"일 뿐이라 크게 신경 쓰지 않고 있었는데, 위에서 언급한 ActiveVIEW::Tempalte::Error보다 앞서 동일한 시점에 MaxMindDB 오류가 발생하고 있습니다.

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 오류(경고)가 관리자 계정 로그인을 차단하고, 그 결과 “Oops” 페이지가 표시되는 원인이 되는 것일까요? 아니면 여기 있는 버그의 일부일까요?

이것이 수동 설정 과정에서 maxmind 구성이 잘못되어 발생한 문제일까요?

일부 지역에서는 Maxmind 파일에 대한 액세스가 차단됩니다. 특히 중국에서 이를 확인한 적이 있습니다.

감사합니다. 이 Discourse 서버는 중국에 위치해 있지 않으며, 로그인하려는 관리자 사용자도 중국에 있지 않습니다. 또한 MaxMindDB가 설정된 적이 없거나, 부분적으로 설정되었더라도 완료되지 않았을 것이라고 생각합니다.

관리자 설정 화면에서 MaxMindDB 설정을 희미하게 기억하고 있지만, 지금은 아무것도 찾을 수 없습니다.

또한 방금 무언가를 깨달았습니다. /logs를 보려면 관리자로 로그인되어 있어야 하므로, 해당 관리자 사용자는 로그를 볼 수 있고, 거기서 “사이트로 돌아가기” 링크를 통해 /admin으로 이동할 수 있습니다. 하지만 그곳에서 맥동하는 UFO 오브(파란 원 5개)가 표시되므로, 우회적으로나마 Oops 페이지를 지나간 상태이지만, 여전히 로그인되지 않은 상태입니다. :thinking:

로그에서 이 우회적인 활동이 OP의 오류를 더 많이 발생시키고 있는 것을 볼 수 있습니다.

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로 제어되며, Rails 콘솔에서 false로 설정됩니다:

SiteSetting.enable_upcoming_changes = false

그러나 이 작업에는 터미널/서버 접근 권한이 필요하므로, 자체 호스팅(self-hosted) 설치 환경에서만 가능합니다.

감사합니다, rails 콘솔에서 해당 명령어를 실행해 봤는데 "command not found"라고 뜨네요 :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를 입력하고 그 안에서 작업을 수행할 수도 있습니다.

나는 항상 약간 어지러움을 느끼는데, 루트 셸이라고 하면 ./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가 되어야 하는데, 이 명령어에서 무엇을 수정해야 하는지 모르겠습니다. 이 동작은 단순히 "find"로 이해했는데, => 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로 변경되어 있었습니다.

로그인도 시도해봤지만 여전히 오류가 뜨네요. 다시 빌드해야 할까요?

다시 돌아가서 말하자면… 당시 저는 예외를 발생시키는 코드가 실행되지 않기를 바라며 관리자 설정을 변경하려 하고 있었습니다.

하지만 우리가 정말 확인하고 싶은 것은 수정이 필요한 코드 버그가 있는지, 아니면 데이터베이스에 있어서는 안 되는 이상한 값이 있는지입니다. 혹은 둘 다일 수도 있죠.

백트레이스는 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

데이터 탐색 쿼리를 실행하여 관리자 계정의 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