FIX: Job exception: undefined method `email' for nil:NilClass

FIX: Job exception: undefined method `email’ for nil:NilClass

It seems that due to jobs being asynchronous and wrapping code in a DistributedMutex that by the time we run the UserAvatar#update_gravatar! job that the user/user email might be destroyed.

This patch checks before a call to user.email_hash to make sure the user and primary email exist to prevent the exception. If not present, the job exits as there’s nothing to do because we are probably running after the user was destroyed for some reason.

diff --git a/app/models/user_avatar.rb b/app/models/user_avatar.rb
index e72adb8..ddb3c6a 100644
--- a/app/models/user_avatar.rb
+++ b/app/models/user_avatar.rb
@@ -16,6 +16,10 @@ class UserAvatar < ActiveRecord::Base
         self.update!(last_gravatar_download_attempt: Time.now)
 
         max = Discourse.avatar_sizes.max
+
+        # The user could be deleted before this executes
+        return if user.blank? || user.primary_email.blank?
+
         email_hash = user_id == Discourse::SYSTEM_USER_ID ? User.email_hash("info@discourse.org") : user.email_hash
         gravatar_url = "https://www.gravatar.com/avatar/#{email_hash}.png?s=#{max}&d=404"
 
diff --git a/spec/models/user_avatar_spec.rb b/spec/models/user_avatar_spec.rb
index fd28ca4..d30a334 100644
--- a/spec/models/user_avatar_spec.rb
+++ b/spec/models/user_avatar_spec.rb
@@ -106,6 +106,13 @@ describe UserAvatar do
       end
     end
 
+    it "should not raise an error when there's no primary_email" do
+      avatar.user.primary_email.destroy
+      avatar.user.reload
+
+      # If raises an error, test fails
+      avatar.update_gravatar!
+    end
   end
 
   context '.import_url_for_user' do

GitHub sha: 57ee779b

2 Likes