From 60e7365256ddd055b3cc59a28c2288b37ad6bf29 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 17 Mar 2026 12:51:06 +0900 Subject: [PATCH] Fix NoMethodError in Gem.try_activate when activation conflicts occur When `find_unloaded_by_path` returns nil, the subsequent `spec.name` call raises NoMethodError because `spec` has been overwritten. Save the gem name before reassigning `spec`. Fixes https://bugs.ruby-lang.org/issues/21954 Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/rubygems.rb | 3 ++- test/rubygems/test_gem.rb | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/rubygems.rb b/lib/rubygems.rb index 55e214e8631f..75d04efbe75e 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -193,8 +193,9 @@ def self.try_activate(path) begin spec.activate rescue Gem::LoadError => e # this could fail due to gem dep collisions, go lax + name = spec.name spec = Gem::Specification.find_unloaded_by_path(path) - spec ||= Gem::Specification.find_by_name(spec.name) + spec ||= Gem::Specification.find_by_name(name) if spec.nil? raise e else diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 74c8953904f2..4293bc5ba817 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1213,6 +1213,28 @@ def test_try_activate_returns_true_for_activated_specs assert Gem.try_activate("b"), "try_activate should still return true" end + def test_try_activate_does_not_raise_no_method_error_on_activation_conflict + a1 = util_spec "a", "1.0" do |s| + s.files << "lib/a/old.rb" + end + + a2 = util_spec "a", "2.0" do |s| + s.files << "lib/a/old.rb" + s.files << "lib/a/new_file.rb" + end + + install_specs a1, a2 + + # Activate the older version + gem "a", "= 1.0" + + # try_activate a file only in the newer version should not raise + # NoMethodError on nil (https://bugs.ruby-lang.org/issues/21954) + assert_nothing_raised do + Gem.try_activate("a/new_file") + end + end + def test_spec_order_is_consistent b1 = util_spec "b", "1.0" b2 = util_spec "b", "2.0"