Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Job failed to load: undefined class/module User::Identity #779

Open
bbrealnex opened this issue Feb 12, 2015 · 24 comments
Open

Job failed to load: undefined class/module User::Identity #779

bbrealnex opened this issue Feb 12, 2015 · 24 comments

Comments

@bbrealnex
Copy link

This is driving me batty, mostly due to the random nature of it.

We are running Rails 4.1 and I have a simple ActiveResource (not ActiveRecord) object called "User" with a method called "update_metadatas" (it takes a json hash as a param). So I'll load up a User object (let's call it u) and then call u.update_metadatas(data). Works great. However, when I do u.delay.update_metadatas(data), things go screwy.

Seemingly depending on the time or day or direction of the wind (ok not really), the above job will immediately fail with:

Job failed to load: undefined class/module User::Identity

The errors aren't that revealing.

Sometimes it will work great with no problems. This behavior happens on both development (local workstation) and production (Heroku).

My guess is that this is a preloading issue . . . i.e., it seems random only because it is affected by when the worker runs (before or after when the rest of the application loads). For example I'll have all the jobs fail for a 2 hour period, and then they'll start working again. I tried the suggestion about turning off config.threadsafe! in production.rb for rake tasks, but that doesn't work for Rails 4.1. I tried the suggestion of adding an initializer like "require 'user'", but that didn't help.

ANY ideas?

P.S. I also run Puma, not sure if that matters (I don't believe Puma is used for the rake tasks though).

@albus522
Copy link
Member

The error says it can't find User::Identity. Which means that is not cleanly autoloading. Look for where that comes from and determine why that wouldn't load.

@bbrealnex
Copy link
Author

Yeah, I saw that, no idea where that is coming from. Will continue investigating, wasn't sure if that was more of a generic error.

@halrogers-claritas
Copy link

I'm having the same issue. For some reason delayed jobs isn't autoloading classes properly. Even manually requiring job classes via an initializer isn't fixing this issue for me.

@albus522
Copy link
Member

albus522 commented Mar 5, 2015

We don't do any loading or autoloading. That is all rails and usually means you have things defined in an unusual way

@raldred
Copy link

raldred commented May 28, 2015

I'm getting this when I have a job that uses a one of my own modules in the payload.
Maybe this is a serialisation problem? or an issue with Rails auto loading

@theCuriousJi
Copy link

I've been having this issue too, and it is seemingly random. Anyone come up with a solution?

@brunzino
Copy link

I got this error too, with the undefined class/module being the name of my Custom Job Struct. This issue comes up for me on my staging server, but not on local / development environment. The delayed job is being called within a rake task.

FWIW: ssh'ing in and manually restarting the daemon (a la bin/delayed_job restart) allowed my job to run without the error.

@DMcKinnon-mdsol
Copy link

DMcKinnon-mdsol commented Aug 19, 2016

I'm also randomly getting a similar error (a different class fails to load for me). Sometimes my DJs work, and often they fail with this error. Has anyone come up with a solution?

@brunzino
Copy link

@DMcKinnon-mdsol, it turns out this whole time I was dealing with this issue, there were multiple instances of the daemon running (due to a faulty deploy script). There are some instructions here for seeing how many instances of delayed_jobs daemon are running and killing them.

@DMcKinnon-mdsol
Copy link

Oh, cool. This might actually be my problem, too. Thanks!

@dvmorris
Copy link

dvmorris commented Nov 2, 2016

I am getting this error, and the suggestion to include a custom initializer that loads the missing class did not work. Also, the suggestion of restarting the delayed_job worker did not work. I don't have multiple delayed_job workers running on the machine either.

Has anyone else figured out another solution? It does not happen every time, only sometimes, but I cannot determine a pattern that makes sense. Here is an example of the failure message:

Job failed to load: undefined class/module NotificationMailer. Handler: "--- !ruby/object:Delayed::PerformableMailer\nobject: !ruby/class 'NotificationMailer'\nmethod_name: :notification\nargs:\n- !ruby/*****\n"
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/backend/base.rb:87:in `rescue in payload_object'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/backend/base.rb:85:in `payload_object'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/backend/base.rb:132:in `max_run_time'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:265:in `max_run_time'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:204:in `block in run'
/usr/local/lib/ruby/2.2.0/benchmark.rb:303:in `realtime'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:203:in `run'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:280:in `block in reserve_and_run_one_job'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `call'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `block in initialize'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `call'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `execute'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:40:in `run_callbacks'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:280:in `reserve_and_run_one_job'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:187:in `block in work_off'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:186:in `times'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:186:in `work_off'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:150:in `block (4 levels) in start'
/usr/local/lib/ruby/2.2.0/benchmark.rb:303:in `realtime'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:149:in `block (3 levels) in start'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `call'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `block in initialize'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `call'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `execute'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:40:in `run_callbacks'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:148:in `block (2 levels) in start'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:147:in `loop'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:147:in `block in start'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/plugins/clear_locks.rb:7:in `call'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/plugins/clear_locks.rb:7:in `block (2 levels) in <class:ClearLocks>'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:79:in `call'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:79:in `block (2 levels) in add'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `call'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `block in initialize'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:79:in `call'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:79:in `block in add'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `call'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `execute'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:40:in `run_callbacks'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/worker.rb:146:in `start'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/command.rb:124:in `run'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/command.rb:112:in `block in run_process'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons/application.rb:265:in `call'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons/application.rb:265:in `block in start_proc'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons/daemonize.rb:84:in `call'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons/daemonize.rb:84:in `call_as_daemon'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons/application.rb:269:in `start_proc'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons/application.rb:295:in `start'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons/controller.rb:56:in `run'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons.rb:193:in `block in run_proc'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons/cmdline.rb:88:in `call'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons/cmdline.rb:88:in `catch_exceptions'
/usr/local/bundle/gems/daemons-1.2.3/lib/daemons.rb:192:in `run_proc'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/command.rb:110:in `run_process'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/command.rb:91:in `block in daemonize'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/command.rb:89:in `times'
/usr/local/bundle/gems/delayed_job-4.0.6/lib/delayed/command.rb:89:in `daemonize'
/opt/bedboard2admin/bin/delayed_job:5:in `<main>'

I tried creating a file called config/initializers/custom.rb with the following line:

require 'notification_mailer'

But that did not seem to help. Here is my bin/delayed_job script for reference:

#!/usr/bin/env ruby

require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require 'delayed/command'
Delayed::Command.new(ARGV).daemonize

And config/environment.rb, which is referenced by that file:

# Load the Rails application.
require File.expand_path('../application', __FILE__)

# Initialize the Rails application.
AppName::Application.initialize!

And config/application.rb, which is referenced by that environment.rb:

require File.expand_path('../boot', __FILE__)

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Bedboard2
  class Application < Rails::Application
    # some config lines omitted here...

    config.autoload_paths << Rails.root.join('lib')

    # some config lines omitted here...
  end
end

And config/boot.rb:

# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)

require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])

I'm just confused as to why it works sometimes, and doesn't work other times. The missing file is located in app/mailers/notification_mailer.rb. Should I explicitly add app/mailers to the config.autoload_paths in application.rb?

Also, here is a sample of my delayed_job.log file from our production server:

I, [2016-11-02T18:43:03.656246 #12782]  INFO -- : 2016-11-02T18:43:03+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861072) RUNNING
I, [2016-11-02T18:43:03.948485 #12782]  INFO -- : 2016-11-02T18:43:03+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861072) COMPLETED after 0.2921
I, [2016-11-02T18:43:03.953833 #12782]  INFO -- : 2016-11-02T18:43:03+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861073) RUNNING
I, [2016-11-02T18:43:04.129653 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861073) COMPLETED after 0.1757
I, [2016-11-02T18:43:04.134292 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861074) RUNNING
I, [2016-11-02T18:43:04.282733 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861074) COMPLETED after 0.1482
I, [2016-11-02T18:43:04.287293 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861075) RUNNING
I, [2016-11-02T18:43:04.455671 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861075) COMPLETED after 0.1682
I, [2016-11-02T18:43:04.460556 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861076) RUNNING
I, [2016-11-02T18:43:04.637698 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861076) COMPLETED after 0.1770
I, [2016-11-02T18:43:04.642223 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861077) RUNNING
I, [2016-11-02T18:43:04.928426 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861077) COMPLETED after 0.2860
I, [2016-11-02T18:43:04.933008 #12782]  INFO -- : 2016-11-02T18:43:04+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861078) RUNNING
I, [2016-11-02T18:43:05.142750 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861078) COMPLETED after 0.2095
I, [2016-11-02T18:43:05.149941 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861079) RUNNING
I, [2016-11-02T18:43:05.313470 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861079) COMPLETED after 0.1634
I, [2016-11-02T18:43:05.318028 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861080) RUNNING
I, [2016-11-02T18:43:05.473159 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861080) COMPLETED after 0.1550
I, [2016-11-02T18:43:05.477747 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861081) RUNNING
I, [2016-11-02T18:43:05.651576 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861081) COMPLETED after 0.1737
I, [2016-11-02T18:43:05.656133 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861082) RUNNING
I, [2016-11-02T18:43:05.815682 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861082) COMPLETED after 0.1594
I, [2016-11-02T18:43:05.820303 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861083) RUNNING
I, [2016-11-02T18:43:05.981684 #12782]  INFO -- : 2016-11-02T18:43:05+0000: [Worker(delayed_job host:fff2a1b96b42 pid:12782)] Job NotificationMailer.new_case_notification (id=861083) COMPLETED after 0.1612

The worker is clearly working sometimes, but no failures show up in the log. The failures only show up in the delayed_jobs table in the database.

@stevebooks
Copy link

+1 I am getting this as well, seems to be random and I can't duplicate it if I login to the console and make the same call.

@ryankilroy
Copy link

We were encountering this error (Rails 5.0.2 and DelayedJob 4.1.2):
Job failed to load: undefined class/module Foo::Bar

We tried require 'foo/bar' in our initializer/delayed_job.rb, but that didn't work.

However, require_relative '../../lib/foo/bar' did work. Seems like delayed jobs might be doing some weird autoloading on it's workers.

@frewsxcv
Copy link

frewsxcv commented Aug 3, 2017

I'm not sure if it's helpful to anyone besides me, I use rake to start my delayed_job workers, and I just learned that rails overrides eager_load to be false for all rake commands. This was causing issues with undefined class names for me

@jorge-fans
Copy link

So I just ran into this issue and I can confirmed that after reading this the only think i needed to do was adding the require 'foo_bar' on my initializer/delayed_job.rb and it worked

@rogeralexmiller
Copy link

I was having uninitialized class errors and the issue was due to my worker pools running off of an older release. See issue #911.

@jcammmmm
Copy link

jcammmmm commented Oct 8, 2017

In
config/initializers/application.rb
add at the end the following line
load(relative/path/to/your/rubyfile)

in my case I needed delay one method from Device.rb that I placed in lib folder...

@stevebooks
Copy link

I looked deeper into my stack trace and noticed that psych was doing some class loading. I then read this SO about it having issues resolving serialized classes: https://stackoverflow.com/questions/4705867/rails-doesnt-load-classes-on-deserializing-yaml-marshal-objects

I added this monkey patch (for Rails4) and haven't had any problems since:

module Psych::Visitors
  ToRuby.class_eval do
    alias :resolve_class_without_autoload :resolve_class
    def resolve_class klassname
      begin
        require_dependency klassname.underscore
      rescue NameError, LoadError
      end
      resolve_class_without_autoload klassname
    end
  end
end

@maxshelley
Copy link

I think I'm also being affected by the same issue, here's the error message I'm getting:

Job failed to load: undefined class/module ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Integer

As with the other above, it's intermittent and I can't see what's causing it.

App is on Heroku, using DJ to send emails with a worker. Because it's an ActiveRecord class/module that isn't being found, would that still be an autoloading issue in Rails?

Is the monkey patch above preventing the error from bubbling up from Psych?

@albus522
Copy link
Member

@maxshelley did you recently do a rails upgrade? That looks more like an ActiveRecord internal that may have moved between versions.

@maxshelley
Copy link

@albus522 Yes, we have, but that errors seem to occurring for jobs that were, I think, created after the update. I don't feel like I've brought enough information to this conversation, I'm going to dig further, thank you for taking the time to respond and I think you're right about the Rails update being part of my issue.

@ERRECabrera
Copy link

I made a pull request to help with this problem.
Meanwhile you can use this lines

# config/initializers/delayed_job.rb

# Monkey patch to use old class references
module Psych

  class << self; attr_accessor :old_class_references end
  @old_class_references = {}

  class ClassLoader
    private

    def find klassname
      klassname = ::Psych.old_class_references[klassname] || klassname
      @cache[klassname] ||= resolve(klassname)
    end
  end

  module Visitors
    class ToRuby < Psych::Visitors::Visitor
      def revive klass, node
        if klass.is_a? String
          klassname = ::Psych.old_class_references[klass] || klass
          klass = Kernel.const_get(klassname) rescue klassname
        end
        s = register(node, klass.allocate)
        init_with(s, revive_hash({}, node), node)
      end
    end
  end
end

# Add all old dependencies (hash keys) pointing to new references (hash values)
Psych.old_class_references = {
  'ActiveRecord::AttributeSet' => 'ActiveModel::AttributeSet'
  # ...
}

@joshuapinter
Copy link

joshuapinter commented Dec 31, 2020

Just quickly contributing our situation here.

In one of our views, we were trying to load the handler via YAML.load( job.handler ) and got the following error:

ActionView::Template::Error (undefined class/module Facility):

For some reason, it could not load the Facility model properly, even though this is in our Rails app where the Facility model has already been loaded (and used).

The quick fix we used was literally calling the Facility model prior to calling YAML.load( job.handler ), like this:

<% Facility -%>
<%= YAML.load( job.handler ).object.name %>

Not sure what the root issue is but maybe that will help somebody in the meantime.

Cheers.

@MittalPatel-BTC
Copy link

@DMcKinnon-mdsol, it turns out this whole time I was dealing with this issue, there were multiple instances of the daemon running (due to a faulty deploy script). There are some instructions here for seeing how many instances of delayed_jobs daemon are running and killing them.

Thanks! This helps me to solve my issue! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests