Skip to content

Fix: Ruby LoadError - cannot load such file

FixDevs ·

Quick Answer

Resolve Ruby's LoadError by checking gem installation, fixing load paths, verifying Bundler setup, and ensuring correct require statements.

The Error

You try to run a Ruby script or start a Rails application and get this:

/usr/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb:85:in `require': cannot load such file -- nokogiri (LoadError)
	from /usr/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb:85:in `require'
	from app.rb:1:in `<main>'

Or a shorter version:

LoadError: cannot load such file -- some_gem

You might also see variations like:

`require': cannot load such file -- ./lib/my_module (LoadError)

All of these mean the same thing: Ruby searched its load path for the file or gem you specified in a require statement and couldn’t find it. The file either doesn’t exist where Ruby is looking, the gem isn’t installed, or there’s a mismatch between your Ruby environment and where the gem lives.

Why This Happens

When you call require 'something' in Ruby, the interpreter searches through every directory listed in $LOAD_PATH (also accessible as $:) looking for a file named something.rb or a native extension named something.so (or .bundle on macOS). If Ruby reaches the end of the list without finding a match, it raises LoadError.

The most common causes:

  • The gem isn’t installed. You’re requiring a gem that was never installed with gem install or bundle install.
  • Bundler isn’t being used. Your Gemfile lists the gem, but you’re running the script without bundle exec, so Bundler hasn’t added the gem’s path to $LOAD_PATH.
  • Wrong Ruby version. You have multiple Ruby versions via rbenv or rvm, and the gem is installed for a different version than the one currently active.
  • The require path is wrong. You’re using require when you should use require_relative, or the file path is simply misspelled.
  • Native extension build failure. The gem installed but its C extension didn’t compile properly, so the .so/.bundle file is missing.
  • Platform-specific gem missing. The gem has platform variants (like nokogiri or grpc), and the one for your OS or architecture isn’t installed.

Fix 1: Install the Missing Gem

The most straightforward fix. If the gem isn’t installed, install it:

gem install nokogiri

To verify whether a gem is already installed:

gem list nokogiri

This prints the installed versions. If nothing appears, the gem isn’t installed for your current Ruby.

You can also search for partial matches:

gem list --local | grep nokogiri

If the gem installs successfully but you still get the error, the gem may be installed for a different Ruby version. Check which Ruby you’re using:

ruby --version
which ruby

Then verify the gem is installed for that specific Ruby:

gem env home

This shows the directory where gems are stored. Make sure it matches your active Ruby installation.

Fix 2: Run with bundle exec

If your project uses a Gemfile, you need to run your script through Bundler. Bundler sets up $LOAD_PATH to include only the gems specified in your Gemfile.lock:

# Wrong -- Ruby doesn't know about your Gemfile
ruby app.rb

# Correct -- Bundler loads the gem paths first
bundle exec ruby app.rb

For Rails projects, this applies to all commands:

# Wrong
rails server
rake db:migrate

# Correct
bundle exec rails server
bundle exec rake db:migrate

If you haven’t run bundle install yet, do that first:

bundle install

This reads your Gemfile, resolves dependencies, and installs all required gems. It also generates a Gemfile.lock that pins exact versions.

Common Mistake: Running gem install some_gem instead of adding it to your Gemfile and running bundle install. While gem install makes the gem available globally, projects using Bundler isolate their dependencies. If your project has a Gemfile, always add gems there: bundle add some_gem or manually edit the Gemfile and run bundle install.

Fix 3: Add the Gem to Your Gemfile

If you’re in a Bundler-managed project and the gem isn’t in your Gemfile, Bundler won’t load it even if it’s installed globally.

Add it to your Gemfile:

# Gemfile
source 'https://rubygems.org'

gem 'nokogiri'
gem 'httparty', '~> 0.21'
gem 'puma', '>= 5.0'

Then install:

bundle install

You can also use the bundle add command, which edits the Gemfile and runs install in one step:

bundle add nokogiri

If you need a gem only in specific environments (development, test), use groups:

# Gemfile
group :development, :test do
  gem 'rspec'
  gem 'pry'
end

Fix 4: Fix require vs require_relative

require and require_relative behave differently, and using the wrong one is a common source of LoadError.

require searches $LOAD_PATH for the file. It’s used for gems and libraries:

require 'json'        # Standard library
require 'nokogiri'    # Installed gem

require_relative loads a file relative to the current file’s directory. It’s used for your own project files:

# If your file structure is:
# lib/
#   main.rb
#   utils/
#     helper.rb

# In lib/main.rb:
require_relative 'utils/helper'   # Correct -- loads lib/utils/helper.rb
require './utils/helper'           # Wrong -- relative to working directory, not file
require 'utils/helper'             # Wrong -- searches $LOAD_PATH, won't find it

A common error is using require './lib/something'. This works only if you run the script from the project root. If you run it from any other directory, it breaks:

# Fragile -- depends on working directory
require './lib/my_module'

# Robust -- relative to the current file
require_relative '../lib/my_module'

If you’re building a gem or a library with a lib/ directory, the conventional approach is to add lib/ to the load path and then use require:

# In your gemspec or at the top of your entry point:
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
require 'my_module'

Fix 5: Check $LOAD_PATH

If Ruby can’t find your file, inspect where it’s looking:

puts $LOAD_PATH

Or from the command line:

ruby -e 'puts $LOAD_PATH'

This prints every directory Ruby searches when you call require. If your gem or file isn’t in any of these directories, Ruby won’t find it.

You can add directories to the load path in several ways:

From the command line:

ruby -I lib app.rb

In your script:

$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
require 'my_module'

Via the RUBYLIB environment variable:

export RUBYLIB="/path/to/your/lib:$RUBYLIB"
ruby app.rb

For most projects, you shouldn’t need to manually manipulate $LOAD_PATH. If you’re using Bundler, it handles this for you. If you’re building a gem, your gemspec’s spec.require_paths setting (usually ['lib']) takes care of it.

Fix 6: Fix rbenv or rvm Ruby Version Issues

If you manage multiple Ruby versions with rbenv or rvm, gems are installed per-version. A gem installed under Ruby 3.1 isn’t available when you switch to Ruby 3.2.

rbenv

Check your current Ruby version:

rbenv version

See which versions have the gem installed:

rbenv versions
# Switch to each and check
rbenv shell 3.2.2
gem list nokogiri

rbenv shell 3.3.0
gem list nokogiri

If the gem is missing for your current version, install it:

gem install nokogiri

After installing gems, you may need to rehash so that rbenv picks up new executables:

rbenv rehash

Also verify that your project’s .ruby-version file matches the Ruby you expect:

cat .ruby-version

If this file specifies a version you don’t have installed, install it:

rbenv install 3.3.0

rvm

rvm current
rvm list
rvm use 3.2.2
gem install nokogiri

If you’re using gemsets:

rvm gemset list
rvm gemset use myproject
gem install nokogiri

Pro Tip: When switching Ruby versions, always run bundle install again in each project. Your Gemfile.lock may contain platform-specific entries, and gems with native extensions need to be recompiled for each Ruby version. Running bundle install after a version switch ensures everything is built correctly for the active Ruby.

Fix 7: Rebuild Native Extensions

Some gems (like nokogiri, pg, mysql2, ffi, grpc) include C extensions that must be compiled during installation. If the compilation fails silently or partially, the gem appears installed but the shared library file is missing.

Signs of a native extension problem:

LoadError: cannot load such file -- nokogiri/nokogiri

Or:

LoadError: cannot load such file -- pg_ext

To fix this, reinstall the gem and watch for compilation errors:

gem install nokogiri -- --use-system-libraries

If you see errors about missing headers or libraries, install the system dependencies first. This is similar to how pip can fail to build wheels when system libraries are missing.

Ubuntu/Debian:

sudo apt-get install build-essential libxml2-dev libxslt1-dev
gem install nokogiri

macOS:

xcode-select --install
brew install libxml2 libxslt
gem install nokogiri -- --use-system-libraries \
  --with-xml2-include=$(brew --prefix libxml2)/include/libxml2

For the pg gem (PostgreSQL):

# Ubuntu/Debian
sudo apt-get install libpq-dev
gem install pg

# macOS
brew install postgresql
gem install pg

For the mysql2 gem:

# Ubuntu/Debian
sudo apt-get install libmysqlclient-dev
gem install mysql2

# macOS
brew install mysql
gem install mysql2

If you’re using Bundler, reinstall with a clean slate:

bundle pristine
# or force a full reinstall
bundle install --force

Fix 8: Handle Platform-Specific Gems

Some gems ship different versions for different platforms. Bundler 2.2+ handles this with platform locks in the Gemfile.lock. But problems arise when your Gemfile.lock was generated on a different platform.

For example, if you develop on macOS and deploy to Linux, your Gemfile.lock might only include macOS-specific gem variants. This is a common issue with gems like nokogiri, google-protobuf, and grpc.

Add the missing platform:

bundle lock --add-platform x86_64-linux
bundle lock --add-platform aarch64-linux   # For ARM Linux (e.g., AWS Graviton)
bundle lock --add-platform ruby            # For the generic Ruby platform

Then run bundle install again. This updates Gemfile.lock with entries for all specified platforms.

In your Gemfile, you can also specify platform constraints:

# Only install on specific platforms
gem 'wdm', '>= 0.1.0', platforms: [:mingw, :mswin, :x64_mingw]
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

If you’re deploying to Docker containers, make sure you run bundle install inside the container (or during the Docker build), not on the host. The gems need to be compiled for the container’s OS and architecture.

Fix 9: Fix Circular or Conditional Requires

Ruby handles circular requires more gracefully than some languages, but they can still cause LoadError in certain situations. If file A requires file B, and file B requires file A, the second require is skipped (Ruby tracks already-loaded files in $LOADED_FEATURES). But this means some constants or methods from file A might not be defined yet when file B tries to use them.

This can manifest as a LoadError if one file conditionally defines something that another file expects:

# lib/parser.rb
require_relative 'lexer'

module Parser
  def self.parse(input)
    Lexer.tokenize(input)
  end
end
# lib/lexer.rb
require_relative 'parser'   # This won't re-load parser.rb

module Lexer
  def self.tokenize(input)
    # ...
  end
end

The fix is to restructure your requires so that dependencies flow in one direction, or use autoloading:

# Using Ruby's autoload
module MyApp
  autoload :Parser, 'my_app/parser'
  autoload :Lexer, 'my_app/lexer'
end

In Rails applications, the autoloader (Zeitwerk) handles this automatically. If you’re getting LoadError in a Rails app for your own code, make sure your file naming follows Rails conventions: MyModule::MyClass should live in app/models/my_module/my_class.rb.

Fix 10: Verify the Gem Name vs Require Name

Just like Python packages that have different install and import names, some Ruby gems have a gem name that differs from the require name.

Common mismatches:

gem install namerequire nameNotes
activerecordactive_recordAll Active* gems use underscores
activesupportactive_support
actionmaileraction_mailer
aws-sdk-s3aws-sdk-s3Matches, but the module is Aws::S3
google-protobufgoogle/protobufUses path separator
ruby-progressbarruby-progressbarMatches, but easy to try progressbar
rspecrspecMatches, but sub-gems differ: rspec-core requires rspec/core
net-httpnet/httpStandard library, uses path separator
net-smtpnet/smtpBecame a bundled gem in Ruby 3.1
sqlite3sqlite3Matches, but native extension issues are common

If you’re unsure about the correct require name, check the gem’s documentation or look at its gemspec:

# Find the gem's installation directory
gem contents nokogiri | head -20

# Or look at the lib directory
gem which nokogiri

The gem which command is particularly useful. It prints the exact file path that require would load, or an error if it can’t find it.

Fix 11: Handle Bundled Gems Removed from Ruby Standard Library

Starting with Ruby 3.0 and continuing through 3.1, 3.2, and 3.3, several libraries that were previously part of Ruby’s standard library have been extracted into separate gems. If you upgrade Ruby and suddenly get LoadError for something that used to work, this is likely why.

Libraries extracted in recent Ruby versions include:

  • Ruby 3.1: net-ftp, net-imap, net-pop, net-smtp, matrix, prime, debug
  • Ruby 3.2: benchmark, bigdecimal, cgi, date (partially)
  • Ruby 3.4: ostruct, pstore, rdoc

To fix this, add the gem explicitly to your Gemfile:

# Gemfile
gem 'net-smtp'
gem 'net-pop'
gem 'net-imap'
gem 'bigdecimal'

Or install it directly:

gem install net-smtp

You’ll often see warnings before the full removal:

warning: <gem_name> was loaded from the standard library, but will no longer be part of
the default gems since Ruby 3.4.0. Add <gem_name> to your Gemfile or gemspec.

Don’t ignore these warnings. Add the gems to your Gemfile before upgrading Ruby to avoid unexpected errors in your CI pipeline.

Fix 12: Fix Docker and Container Environments

If your Ruby application works locally but throws LoadError inside a Docker container, the issue is almost always that gems weren’t installed in the container, or they were installed for the wrong platform.

A properly structured Dockerfile for a Ruby application:

FROM ruby:3.3-slim

# Install system dependencies for native extensions
RUN apt-get update -qq && \
    apt-get install -y build-essential libpq-dev nodejs && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Copy Gemfile first (for Docker layer caching)
COPY Gemfile Gemfile.lock ./
RUN bundle install --jobs 4 --retry 3

# Then copy the rest of the application
COPY . .

CMD ["bundle", "exec", "ruby", "app.rb"]

Common Docker mistakes:

Not copying Gemfile.lock: Without the lock file, bundle install resolves versions fresh, which might pull incompatible versions.

Installing gems as root but running as non-root: If you switch users after installing gems, the new user might not have access to the gem directory. Set the bundle path:

RUN bundle config set --local path 'vendor/bundle'
RUN bundle install

Missing system libraries: Native extension gems need development headers. Install them before running bundle install. If you’re seeing errors similar to permission denied issues in Docker, make sure the user running the application has read access to the gem installation directory.

Multi-stage builds discarding gems: If you use multi-stage builds, make sure you copy the installed gems from the build stage to the final stage:

FROM ruby:3.3-slim AS builder
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install --path vendor/bundle

FROM ruby:3.3-slim
WORKDIR /app
COPY --from=builder /app/vendor/bundle vendor/bundle
RUN bundle config set --local path 'vendor/bundle'
COPY . .
CMD ["bundle", "exec", "ruby", "app.rb"]

Still Not Working?

Inspect $LOADED_FEATURES

Ruby keeps track of every file it has successfully loaded in $LOADED_FEATURES. You can check if a file was partially loaded or loaded from an unexpected location:

puts $LOADED_FEATURES.grep(/nokogiri/)

If nothing appears, the gem was never loaded. If a path appears but it points to an unexpected location, you have a Ruby version or environment mismatch.

Clear gem cache and reinstall

Sometimes gem installations become corrupted. A clean reinstall can fix things:

# Remove and reinstall a specific gem
gem uninstall nokogiri --all
gem install nokogiri

# With Bundler, clean up unused gems and reinstall
bundle clean --force
bundle install

# Nuclear option: remove all gems and reinstall
# (be careful with this in production)
gem cleanup
bundle install

Check file permissions

On Linux and macOS, gems installed with sudo might have restrictive file permissions that prevent your user from loading them. Avoid using sudo gem install. Instead, configure gem installation to your user directory:

# Set gem installation to user directory
echo 'gem: --user-install' >> ~/.gemrc

# Add user gem bin directory to PATH
export PATH="$(ruby -r rubygems -e 'puts Gem.user_dir')/bin:$PATH"

Or better yet, use a Ruby version manager (rbenv or rvm) which installs gems to user-accessible directories by default.

Verify the gem is loadable

Test in an interactive Ruby session:

irb
require 'nokogiri'
# => true (success) or LoadError (still broken)

# Check where Ruby found it
puts Gem.loaded_specs['nokogiri'].full_gem_path

If it works in irb but not in your script, the difference is likely your working directory, Bundler configuration, or how you’re invoking Ruby.

Spring and other preloaders

If you’re using Rails with Spring (the application preloader), it can cache outdated gem paths. Stop Spring and try again:

bin/spring stop
bundle exec rails server

Related: If you’re seeing a similar error in Node.js, check Fix: Error Cannot find module (Node.js). For Go module issues, see Fix: go module not found.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles