Defect #35174
closed
Internal Error when accessing the home page of some projects
Added by Miguel Moquillon over 3 years ago.
Updated over 3 years ago.
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
I cannot reproduce it, can you tell us more about your environment? Please see Submissions.
- Status changed from New to Needs feedback
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
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 %>
I don't know why nil is included, I think it needs improvement if it can happen in other environments.
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?
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?
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)
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#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
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.)
Can I remove it?
you should do a backup first before such actions. But each member should refer to an existing user.
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...
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.
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.
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.
- 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.
Also available in: Atom
PDF