From 60e7365256ddd055b3cc59a28c2288b37ad6bf29 Mon Sep 17 00:00:00 2001
From: Hiroshi SHIBATA <hsbt@ruby-lang.org>
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) <noreply@anthropic.com>
---
 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"
