From 1eab7ede9b3b4bf4ec0ceb89d4c8622689af778c Mon Sep 17 00:00:00 2001 From: Kyle Keesling Date: Thu, 11 Jun 2026 11:58:05 -0400 Subject: [PATCH] fix(rails): make Action Cable handle_open/handle_close overrides public MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rails 8.2 decoupled the Action Cable connection from the socket (rails/rails#50979): ActionCable::Server::Socket now invokes connection.handle_open and connection.handle_close from outside the connection. sentry-rails' prepended overrides were private, so on Rails main every cable connection raises NoMethodError (private method 'handle_open' called for an instance of ApplicationCable::Connection) before the welcome message is sent — clients never receive pings or broadcasts and reconnect in a loop. The error only reaches the Rails logger (Sentry isn't initialized for the failing connection path), so it fails silently. On Rails < 8.2 these methods are only called internally on self, where visibility doesn't matter, so making them public is safe everywhere. Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 6 ++++++ sentry-rails/lib/sentry/rails/action_cable.rb | 9 +++++++-- .../spec/sentry/rails/action_cable_spec.rb | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17c74116f..b4f4b4bdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +### Bug Fixes 🐛 + +- (rails) Make Action Cable `handle_open`/`handle_close` overrides public so Rails 8.2's `ActionCable::Server::Socket` can invoke them ([rails/rails#50979](https://github.com/rails/rails/pull/50979)); the private overrides raised `NoMethodError` on every cable connection, killing all websocket traffic + ## 6.6.2 ### Bug Fixes 🐛 diff --git a/sentry-rails/lib/sentry/rails/action_cable.rb b/sentry-rails/lib/sentry/rails/action_cable.rb index 222aab1b8..d2f8d61ad 100644 --- a/sentry-rails/lib/sentry/rails/action_cable.rb +++ b/sentry-rails/lib/sentry/rails/action_cable.rb @@ -57,8 +57,13 @@ def finish_transaction(transaction, status_code) end module Connection - private - + # These overrides must stay public: Rails 8.2 decoupled the Action + # Cable connection from the socket (rails/rails#50979), and + # ActionCable::Server::Socket now invokes connection.handle_open and + # connection.handle_close from outside the connection. With private + # overrides every cable connection raises NoMethodError before the + # welcome message is sent. On older Rails versions these methods are + # only called internally, so public visibility is harmless there. def handle_open ErrorHandler.capture(self, transaction_name: "#{self.class.name}#connect") do super diff --git a/sentry-rails/spec/sentry/rails/action_cable_spec.rb b/sentry-rails/spec/sentry/rails/action_cable_spec.rb index e47ad2efa..9f7d74cf2 100644 --- a/sentry-rails/spec/sentry/rails/action_cable_spec.rb +++ b/sentry-rails/spec/sentry/rails/action_cable_spec.rb @@ -73,6 +73,20 @@ def disconnect transport.events = [] end + describe "Connection method visibility" do + before do + make_basic_app + end + + # Rails 8.2 (rails/rails#50979) invokes connection.handle_open and + # connection.handle_close from ActionCable::Server::Socket, outside the + # connection — private overrides break every cable connection there. + it "keeps handle_open and handle_close public" do + expect(Sentry::Rails::ActionCableExtensions::Connection.public_method_defined?(:handle_open)).to eq(true) + expect(Sentry::Rails::ActionCableExtensions::Connection.public_method_defined?(:handle_close)).to eq(true) + end + end + describe "Connection" do before do make_basic_app