ruby/ruby · error · Bundler::PathError

The path `#{expanded_path}` does not exist.

Error message

The path `#{expanded_path}` does not exist.

What it means

Raised from Bundler::Source::Path#specs when the expanded path for a `:path` gem source simply does not exist on disk (File.exist? is false, the sibling branch of the 'is not a directory' case). The Gemfile references a location that is not present on this machine, so Bundler cannot load any gemspec from it.

Source

Thrown at lib/bundler/source/path.rb:204

              s.platform = Gem::Platform::RUBY
              s.summary  = "Fake gemspec for #{@name}"
              s.relative_loaded_from = "#{@name}.gemspec"
              s.authors = ["no one"]
              if expanded_path.join("bin").exist?
                executables = expanded_path.join("bin").children
                executables.reject! {|p| File.directory?(p) }
                s.executables = executables.map {|c| c.basename.to_s }
              end
            end
          end
        else
          message = String.new("The path `#{expanded_path}` ")
          message << if File.exist?(expanded_path)
            "is not a directory."
          else
            "does not exist."
          end
          raise PathError, message
        end

        index
      end

      def relative_path(path = self.path)
        if path.to_s.start_with?(root_path.to_s)
          return path.relative_path_from(root_path)
        end
        path
      end

      def generate_bin(spec, options = {})
        gem_dir = Pathname.new(spec.full_gem_path)

        # Some gem authors put absolute paths in their gemspec
        # and we have to save them from themselves
        spec.files = spec.files.filter_map do |path|

View on GitHub (pinned to 0e5b888e1c)

Solutions

  1. Check the expanded location relative to the Gemfile's directory and fix the typo, case, or relative level in the :path value
  2. Clone or restore the missing directory (e.g. `git submodule update --init --recursive`)
  3. If the gem lives elsewhere on this machine, use an absolute path or set a local override: `bundle config local.foo /abs/path/to/foo`
  4. Add a quick Gemfile-time guard so the failure names the bad path immediately

Example fix

# before
gem "foo", path: "../common/foo"

# after
gem "foo", path: "../libs/foo"
Defensive patterns

Strategy: validation

Validate before calling

# Ensure every :path source exists relative to the Gemfile before installing
require "bundler"
base = File.dirname(Bundler.default_gemfile)
path_gems.each do |name, rel|
  abs = File.expand_path(rel, base)
  abort "#{name}: path #{abs} does not exist" unless File.directory?(abs)
end

Try / catch

begin
  Bundler::Installer.install(Bundler.root, Bundler.definition)
rescue Bundler::PathError => e
  raise unless e.message.include?("does not exist")
  system("git submodule update --init --recursive")
  retry
end

Prevention

When it happens

Trigger: `gem "foo", path: "../foo"` when ../foo has not been cloned yet; git submodules holding the gem not initialized; case-sensitive path mismatch ("Foo" vs "foo") moving projects between macOS and Linux; relative paths written against a different base directory than the Gemfile's location.

Common situations: Fresh clone where `git clone --recursive` was forgotten; a teammate moved or renamed the folder and committed the Gemfile update but not the folder; monorepo checkouts missing sibling repos; wrong-case paths that worked on case-insensitive filesystems and fail in CI/Docker on Linux.

Related errors


AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21). Data as JSON: /api/errors/473f51b95e095c23. Report an issue: GitHub.