Ruby 3.0.0: `library not found for class Digest::SHA256`

After changig my Rails app’s Gemfile to use Ruby 3.0.0 I get the following error when running bundle install:

~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/digest.rb:16:in 'const_missing': library not found for class Digest::SHA256 -- digest/sha2.so (LoadError)
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/digest.rb:100:in 'block in Digest'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/digest.rb:98:in 'synchronize'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/shared_helpers.rb:208:in 'digest'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/rubygems_gem_installer.rb:45:in 'block in validate_bundler_checksum'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/rubygems/package/file_source.rb:29:in 'open'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/rubygems/package/file_source.rb:29:in 'with_read_io'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/rubygems_gem_installer.rb:44:in 'validate_bundler_checksum'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/rubygems_gem_installer.rb:12:in 'pre_install_checks'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/rubygems/installer.rb:286:in 'install'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/source/rubygems.rb:158:in 'install'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/installer/gem_installer.rb:67:in 'install'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/installer/gem_installer.rb:18:in 'install_from_spec'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/installer/parallel_installer.rb:163:in 'do_install'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/installer/parallel_installer.rb:154:in 'block in worker_pool'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/worker.rb:62:in 'apply_func'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/worker.rb:57:in 'block in process_queue'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/worker.rb:54:in 'loop'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/worker.rb:54:in 'process_queue'
        from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/bundler/worker.rb:88:in 'block (2 levels) in create_threads'

NB: I installed Ruby using rbenv and at first there was an SSL issue during installation, which I fixed (based on some suggestions found online) by pointing to the Homebrew-installed SSL library while running ruby-build (I am on macOS):

RUBY_CONFIGURE_OPTS=--with-openssl-dir=/usr/local/Cellar/openssl@1.1 rbenv install 3.0.0

Ruby itself now works fine, here is the output of ruby --version:

ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]

However irb shows the same error:

$ irb
irb(main):001:0> require 'digest'
=> true
irb(main):002:0> Digest::SHA256
Traceback (most recent call last):
        5: from ~/.rbenv/versions/3.0.0/bin/irb:23:in '<main>'
        4: from ~/.rbenv/versions/3.0.0/bin/irb:23:in 'load'
        3: from ~/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/irb-1.3.0/exe/irb:11:in '<top (required)>'
        2: from (irb):2:in '<main>'
        1: from ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/digest.rb:16:in 'const_missing'
LoadError (library not found for class Digest::SHA256 -- digest/sha2.so)
irb(main):003:0> Digest.constants
=> [:Instance, :Base, :Class, :REQUIRE_MUTEX]

Would someone have suggestions to fix the issue?

Curious. Does ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/x86_64-darwin19/digest/sha2.bundle exist? (or similar?)

Using Pry:

[3] pry(main)> $ Digest

From: /Users/jon/.rbenv/versions/3.0.0/lib/ruby/3.0.0/digest.rb:4
Module name: Digest
Number of lines: 75

module Digest
  # A mutex for Digest().
  REQUIRE_MUTEX = Thread::Mutex.new

  def self.const_missing(name) # :nodoc:
    case name
    when :SHA256, :SHA384, :SHA512
      lib = 'digest/sha2.so'
    else
      lib = File.join('digest', name.to_s.downcase)
    end

    begin
      require lib
    rescue LoadError
      raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1)
    end
    unless Digest.const_defined?(name)
      raise NameError, "uninitialized constant Digest::#{name}", caller(1)
    end
    Digest.const_get(name)
  end

I could not find sha2.so in the require path, but sha2.bundle yes.

Then:

@joallard I have these files, there is no sha2 file:

$ ls ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/x86_64-darwin20/digest/
bubblebabble.bundle     md5.bundle              rmd160.bundle           sha1.bundle

I’ve never used pry but after doing gem install pry I could get the same output as you showed (however, first I had to run require 'digest'):

$ pry
[1] pry(main)> require 'digest'
=> true
[2] pry(main)> $ Digest

From: /Users/sdubois/.rbenv/versions/3.0.0/lib/ruby/3.0.0/digest.rb:4
Module name: Digest
Number of lines: 75

module Digest
  # A mutex for Digest().
  REQUIRE_MUTEX = Thread::Mutex.new

  def self.const_missing(name) # :nodoc:
    case name
    when :SHA256, :SHA384, :SHA512
      lib = 'digest/sha2.so'
    else
      lib = File.join('digest', name.to_s.downcase)
    end

    begin
      require lib
    rescue LoadError
      raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1)
    end
    unless Digest.const_defined?(name)
      raise NameError, "uninitialized constant Digest::#{name}", caller(1)
    end
    Digest.const_get(name)
  end

  # ...

As to your last screenshot it seems to show paths with Ruby 2.7.2 whereas I am trying with 3.0.0. In bash I could run this (after running brew install fd), it does not find any sha2 file:

$ for path in `ruby -e "puts \$:"`; do echo $path; fd sha2 $path; done
/usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash
/Users/sdubois/.rbenv/versions/3.0.0/lib/ruby/site_ruby/3.0.0
/Users/sdubois/.rbenv/versions/3.0.0/lib/ruby/site_ruby/3.0.0/x86_64-darwin20
/Users/sdubois/.rbenv/versions/3.0.0/lib/ruby/site_ruby
/Users/sdubois/.rbenv/versions/3.0.0/lib/ruby/vendor_ruby/3.0.0
/Users/sdubois/.rbenv/versions/3.0.0/lib/ruby/vendor_ruby/3.0.0/x86_64-darwin20
/Users/sdubois/.rbenv/versions/3.0.0/lib/ruby/vendor_ruby
/Users/sdubois/.rbenv/versions/3.0.0/lib/ruby/3.0.0
/Users/sdubois/.rbenv/versions/3.0.0/lib/ruby/3.0.0/x86_64-darwin20

OK I could workaround the issue by uninstalling rbenv (rbenv uninstall 3.0.0 && brew uninstall rbenv) and installing Ruby from Homebrew (brew install ruby). Now I get this :+1:

$ ruby --version
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]
$ irb
irb(main):001:0> require 'digest'
=> true
irb(main):002:0> Digest::SHA256
=> Digest::SHA256

I lost the ability to manage several rubies but hopefully that won’t be too bothersome.

Hmm, that’s sure weird, I’m running Rbenv here as well.

My ls on Ruby 2.7 was an oversight, but mind you, I have a similar result with Ruby 3.0:

~> ls ~/.rbenv/versions/3.0.0/lib/ruby/3.0.0/x86_64-darwin19/digest/
[...]      sha1.bundle*         sha2.bundle*

I don’t see why that would be missing on a new installation. Maybe your installation randomly messed up perhaps?

In any case, if you ever need Rbenv again, you’ll probably be able to use it.

I don’t really understand the problem but I’ve installed 3.0.0 with chruby and ruby-install, brew install ruby-install. “Switching from rbenv to … ruby-install and chruby”.

I believe that the problem is happening because digest is now a gem that you need to explicitly define in your Gemfile

This is stated in the Ruby 3.0 release notes:

The following stdlib files are now default gems and are published on rubygems.org:

  • English
  • tmpdir
  • time
  • tsort
  • un
  • weakref
  • digest

I believe that explicitly adding this as a dependency in your Gemfile or .gemspec should fix the problem.

If you are using Bundler.require you won’t need to do anything else. If you are not, you are probably going to need to call require 'digest' somewhere in your code.

I hope this helps.

Thanks @etagwerker for the tip, however as per my previous comments I got things working just by removing rbenv and reinstalling Ruby 3.0.0 via Homebrew for some reason. I don’t have digest in my Gemfile (nor in Gemfile.lock).

1 Like