Defect #35174
closedInternal Error when accessing the home page of some projects
0%
Description
Since the upgrade from 4.1.2 to 4.2.0 and 4.2.1, when accessing the home page of some of our projects, we have an "Internal Error" page with the following error messages in the log:
ActionView::Template::Error (comparison of NilClass with User failed): 2: <div class="members box"> 3: <h3 class="icon icon-group"><%=l(:label_member_plural)%></h3> 4: <% @principals_by_role.keys.sort.each do |role| %> 5: <p><span class="label"><%= role %>:</span> <%= @principals_by_role[role].sort.collect{|p| link_to_user p}.join(", ").html_safe %></p> 6: <% end %> 7: </div> 8: <% end %> app/views/projects/_members_box.html.erb:5:in `sort' app/views/projects/_members_box.html.erb:5:in `block in _app_views_projects__members_box_html_erb___1165424576507768033_82920' app/views/projects/_members_box.html.erb:4:in `each' app/views/projects/_members_box.html.erb:4:in `_app_views_projects__members_box_html_erb___1165424576507768033_82920' app/views/projects/show.html.erb:132:in `_app_views_projects_show_html_erb___1481690599684784851_82880' lib/redmine/sudo_mode.rb:61:in `sudo_mode'
Note: not all the projects are concerned by this problem.
Files
Updated by Marius BĂLTEANU over 3 years ago
I cannot reproduce it, can you tell us more about your environment? Please see Submissions.
Updated by Marius BĂLTEANU over 3 years ago
- Status changed from New to Needs feedback
Updated by Miguel Moquillon over 3 years ago
Operating system: Ubuntu 20.04.2 LTS
ruby bin/about gives:
sh: 1: svn: not found sh: 1: hg: not found sh: 1: cvs: not found sh: 1: bzr: not found Environment: Redmine version 4.2.1.stable Ruby version 2.7.2-p137 (2020-10-01) [x86_64-linux] Rails version 5.2.5 Environment production Database adapter Mysql2 Mailer queue ActiveJob::QueueAdapters::AsyncAdapter Mailer delivery smtp SCM: Git 2.25.1 Filesystem Redmine plugins: no plugin installed
Our redmine instance is served by Apache2 through passenger: Phusion Passenger(R) 6.0.8
For information, redmine is used since 2010 and was updated at each new release by following the page RedmineUpdate
Updated by Mizuki ISHIKAWA over 3 years ago
I implemented this code on the assumption that @principals_by_role[role]
is an array containing only User records, but in Redmine where the problem occurred, @principals_by_role[role]
seems to have been an array containing user records and nil.
Example:
pry(main)> [User.first, nil, User.second].sort ArgumentError: comparison of NilClass with User failed from (pry):18:in `sort'
I think the problem can be solved by changing the code as follows.
diff --git a/app/views/projects/_members_box.html.erb b/app/views/projects/_members_box.html.erb
index e915ab910a..280f2e3aff 100644
--- a/app/views/projects/_members_box.html.erb
+++ b/app/views/projects/_members_box.html.erb
@@ -2,7 +2,7 @@
<div class="members box">
<h3 class="icon icon-group"><%=l(:label_member_plural)%></h3>
<% @principals_by_role.keys.sort.each do |role| %>
- <p><span class="label"><%= role %>:</span> <%= @principals_by_role[role].sort.collect{|p| link_to_user p}.join(", ").html_safe %></p>
+ <p><span class="label"><%= role %>:</span> <%= @principals_by_role[role].compact.sort.collect{|p| link_to_user p}.join(", ").html_safe %></p>
<% end %>
</div>
<% end %>
Updated by Mizuki ISHIKAWA over 3 years ago
I don't know why nil is included, I think it needs improvement if it can happen in other environments.
Updated by Pavel Rosický over 3 years ago
Miguel - could you check that you don't have any orphan project members?
rails c -e production Member.where.not(user_id: Principal.select(:id)).any?
it should return "false"
this could happen by bypassing Redmine's API and removing a user directly from the database. Any chance you did something like this in the past?
Updated by Miguel Moquillon over 3 years ago
Pavel Rosický wrote:
Miguel - could you check that you don't have any orphan project members?
[...]
it should return "false"this could happen by bypassing Redmine's API and removing a user directly from the database. Any chance you did something like this in the past?
Unfortunately, it returns ... "true".
No, we don't use the Redmine's API to do admin tasks (or it should have been a long time ago). What does mean "orphan project member"? A user that is yet a member of a project but whose account has been deleted?
Updated by Miguel Moquillon over 3 years ago
Ok, by issuing
Member.select(:user_id).where.not(user_id: Principal.select(:id)).distinct
I found the identifier of the user causing the error (I'm not a ruby programmer but I figured out the instruction from your code snippet): there is only one user (an old one).
Can I remove it from the membership of the projects without any consequences by executing the following code (is the code correct?):
Member.delete.where(user_id: 6)
Updated by Pavel Rosický over 3 years ago
if you remove a user from the system, all dependencies like project members are deleted via callbacks
https://github.com/redmine/redmine/blob/master/app/models/principal.rb#L31
however, if you bypass the API, you end up in a situation there's a member entry that refers to a user which doesn't exist in the `users` table.
Mizuki ISHIKAWA's solution is only fixing the consequences of the database inconsistency.
btw: foreign key constraints in the schema should prohibit such actions on the database level, but Redmine doesn't use them, see https://www.redmine.org/boards/4/topics/65243
Updated by Miguel Moquillon over 3 years ago
Pavel Rosický wrote:
if you remove a user from the system, all dependencies like project members are deleted via callbacks
https://github.com/redmine/redmine/blob/master/app/models/principal.rb#L31however, if you bypass the API, you end up in a situation there's a member entry that refers to a user which doesn't exist in the `users` table.
Mizuki ISHIKAWA's solution is only fixing the consequences of the database inconsistency.
btw: foreign key constraints in the schema should prohibit such actions on the database level, but Redmine doesn't use them, see https://www.redmine.org/boards/4/topics/65243
Ok. When I wrote we don't use the Redmine's API, I means we use the Redmine administration page for doing such tasks. (In my mind, Redmine API were meaning REST API.)
Updated by Pavel Rosický over 3 years ago
Can I remove it?
you should do a backup first before such actions. But each member should refer to an existing user.
Updated by Pavel Rosický over 3 years ago
it's hard to guess, how this could happen in your environment. If it used to work in the previous version and you have a backup, try to compare the data, when the user was removed and how...
Updated by Miguel Moquillon over 3 years ago
Pavel Rosický wrote:
Can I remove it?
you should do a backup first before such actions. But each member should refer to an existing user.
Backup of our redmine installation (with database) are performed every night. So in the morning I purged the memberships of the deleted old user by issuing the following command:
Member.where(user_id: 6).destroy_all
According to the Rails documentation,
destroy_all
triggers the execution of all the callbacks of the objects.
Once done, we haven't anymore the internal error when accessing the projects' home page.
Updated by Miguel Moquillon over 3 years ago
Pavel Rosický wrote:
it's hard to guess, how this could happen in your environment. If it used to work in the previous version and you have a backup, try to compare the data, when the user was removed and how...
Unfortunately, we don't keep our backups a long time; we purged them every month.
Updated by Ingo Linde over 3 years ago
Same issue occured here after upgrading to 4.2.1. After removing the orphaned member from the database the issue was resolved.
Thanks for the hints to debug and solve this!
In our case the database inconsistency has persisted at least since 2016. So it is definitely NOT a (recent) migration issue or anything like that.
I can only guess, but I reckon that it has been caused by manual database manipulation back then.
Updated by Marius BĂLTEANU over 3 years ago
- Status changed from Needs feedback to Closed
- Resolution set to Invalid
Ingo Linde wrote:
Same issue occured here after upgrading to 4.2.1. After removing the orphaned member from the database the issue was resolved.
Thanks for the hints to debug and solve this!In our case the database inconsistency has persisted at least since 2016. So it is definitely NOT a (recent) migration issue or anything like that.
I can only guess, but I reckon that it has been caused by manual database manipulation back then.
Thanks Ingo for the info.
I'm closing this issue because these cases can be fixed manually and I don't think that it's a good idea to add a migration to Redmine to delete the orphan members. Please reopen if I'm wrong.