Skip to content

#8180 is still reproducible without --prefer-local on Bundler 4.0.18 #9791

Description

@thyresias

Describe the problem

Bundler installs a regular copy of a gem even when the exact same version is already available as a Ruby default gem.

This appears to be the same underlying behavior reported in #8180. That issue was closed by #8412, but #8412 specifically fixes the behavior when --prefer-local is used. With a normal bundle install, the behavior is still reproducible with Bundler 4.0.18.

In my case this was initially exposed by Ruby LSP, whose generated lockfile referenced io-console 0.8.2. Ruby 4.0.6 already ships io-console 0.8.2 as a default gem, but Bundler downloaded, built, and installed an additional regular copy of io-console 0.8.2.

The issue is reproducible without Ruby LSP.

Environment

> ruby -v
ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +PRISM [x64-mingw-ucrt]
> gem -v
4.0.18

Before the test, io-console 0.8.2 is present only as a default gem:

io-console-0.8.2 | DEFAULT | c:/ruby-4.0.6-x64/lib/ruby/gems/4.0.0/specifications/default/io-console-0.8.2.gemspec

Minimal reproduction

Create a new directory with this Gemfile:

source "https://rubygems.org"

gem "io-console", "0.8.2"

Generate the lockfile:

bundle lock

Then run:

bundle install --verbose

Observed output:

Running `bundle install --verbose` with bundler 4.0.18
Found no changes, using resolution from the lockfile
Using bundler 4.0.18
0:  bundler (4.0.18) from c:/ruby-4.0.6-x64/lib/ruby/gems/4.0.0/specifications/default/bundler-4.0.18.gemspec
HTTP GET https://index.rubygems.org/versions
HTTP 304 Not Modified https://index.rubygems.org/versions
Fetching gem metadata from https://rubygems.org/
Looking up gems ["io-console"]
Fetching io-console 0.8.2
Downloaded io-console in: 0.086s
Installing io-console 0.8.2 with native extensions
Temporarily enhancing PATH for MSYS/MINGW...
Building native extensions. This could take a while...
Installed io-console in: 18.301s
0:  io-console (0.8.2) from c:/ruby-4.0.6-x64/lib/ruby/gems/4.0.0/specifications/default/io-console-0.8.2.gemspec
Bundle complete! 1 Gemfile dependency, 1 gem now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

Afterwards, both specifications exist:

io-console-0.8.2 | NORMAL  | c:/ruby-4.0.6-x64/lib/ruby/gems/4.0.0/specifications/io-console-0.8.2.gemspec
io-console-0.8.2 | DEFAULT | c:/ruby-4.0.6-x64/lib/ruby/gems/4.0.0/specifications/default/io-console-0.8.2.gemspec

So Bundler downloads, compiles, and installs a regular copy of the exact version that is already available as a default gem.

Interestingly, the verbose output then reports the default-gem specification as the one being used:

0:  io-console (0.8.2) from c:/ruby-4.0.6-x64/lib/ruby/gems/4.0.0/specifications/default/io-console-0.8.2.gemspec

--prefer-local behaves as expected

After removing the redundant regular copy and restoring the initial state, running:

bundle install --verbose --prefer-local

does not reinstall the gem:

Running `bundle install --prefer-local --verbose` with bundler 4.0.18
Found no changes, using resolution from the lockfile
Using bundler 4.0.18
0:  bundler (4.0.18) from c:/ruby-4.0.6-x64/lib/ruby/gems/4.0.0/specifications/default/bundler-4.0.18.gemspec
Using io-console 0.8.2
0:  io-console (0.8.2) from c:/ruby-4.0.6-x64/lib/ruby/gems/4.0.0/specifications/default/io-console-0.8.2.gemspec
Bundle complete! 1 Gemfile dependency, 1 gem now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

Expected behavior

For a normal bundle install, if the exact required name and version are already available as a default gem, I would expect Bundler to use that default gem rather than download and install an identical regular copy.

This matters in particular for default gems with native extensions: in this example the unnecessary installation recompiles io-console.

Related issues

Since the original #8180 reproducer did not use --prefer-local, is the current behavior of plain bundle install intentional? If not, #8180 appears to remain reproducible in Bundler 4.0.18.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions