Skip to content

ActionCable instrumentation breaks all /cable connections on Rails 8.2 / main (private handle_open called publicly by Server::Socket) #2975

Description

@kaushgem

Issue Description

sentry-rails instruments ActionCable by prepending Sentry::Rails::ActionCableExtensions::Connection onto the connection, and that module declares #handle_open / #handle_close as private (sentry-rails/lib/sentry/rails/action_cable.rb):

module Connection
  private

  def handle_open
    ErrorHandler.capture(self, transaction_name: "#{self.class.name}#connect") { super }
  end

  def handle_close
    ErrorHandler.capture(self, transaction_name: "#{self.class.name}#disconnect") { super }
  end
end

Rails 8.2 / main decoupled the cable socket from the connection (rails/rails#50979, merged 2026-05-28). ActionCable::Server::Socket now calls the connection back with an explicit receiver, which requires the method to be public:

def handle_open
  @protocol = websocket.protocol
  @connection.handle_open     # explicit receiver -> must be public
  message_buffer.process!
  server.add_connection(@connection)
end

Because the prepended module sits ahead of ActionCable::Connection::Base in the ancestor chain and marks the method private, every /cable upgrade raises NoMethodError. The WebSocket upgrade returns 101, but handle_open raises before welcome is sent, so clients never receive welcome/pings and reconnect-loop forever — no broadcasts (Turbo Streams, presence) are ever delivered. The exception only reaches the Rails logger, not Sentry, since it happens inside the instrumentation wrapper. In Rails' own Connection::Base, both methods are public; the prepended private versions invert the intended visibility.

Reproduction Steps

  1. Rails app tracking rails/rails main (any revision including the ActionCable::Server::Socket extraction; reproduced on 8.2.0.alpha).
  2. Add sentry-rails and configure Sentry.init.
  3. Open a WebSocket to /cable (e.g. a Turbo Stream subscription).
  4. The upgrade raises immediately:
NoMethodError: private method 'handle_open' called for an instance of ApplicationCable::Connection
  actioncable/lib/action_cable/server/socket.rb:127:in 'handle_open'

Expected Behavior

/cable WebSocket connections open normally with Sentry instrumentation active.

Actual Behavior

Every /cable upgrade raises NoMethodError (private method 'handle_open' called ...); the client never receives welcome and reconnect-loops; no broadcasts are delivered.

Ruby Version

4.0.1

SDK Version

sentry-rails 6.6.1 (also reproduces on the latest release 6.6.2 and current master — both still mark these private)

Integration and Its Version

Rails 8.2.0.alpha (rails/rails main, rev 324b65c2dffe17ee03522b39b516f482087f244f) — ActionCable

Sentry Config

Standard Sentry.init; no special config needed to trigger.

Workaround (until a fix ships)

Re-publicize the two methods in an initializer:

Sentry::Rails::ActionCableExtensions::Connection.send(:public, :handle_open, :handle_close)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions