You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
TestHelper: setup_sentry_test ineffective in request specs due to clone_hub_to_current_thread overwriting thread-local hub #2951
setup_sentry_test modifies whichever hub Sentry.get_current_hub returns (the thread-local hub), but in Rails request/integration specs, Sentry::Rack::CaptureExceptions middleware calls Sentry.clone_hub_to_current_thread, which always clones @main_hub — not the thread-local hub that setup_sentry_test modified. This overwrites the test setup entirely.
After the first setup_sentry_test call sets a DummyTransport on @main_hub (because in the main thread, thread-local IS @main_hub), teardown_sentry_test pops the scope but the base layer with DummyTransport remains. Subsequent requests in unrelated tests then capture events to this leftover DummyTransport, and those stale events leak into later tests that use sentry_events.
Since RSpec uses random test order, this manifests as intermittent failures.
Reproduction
require"sentry-ruby"require"sentry/test_helper"includeSentry::TestHelperSentry.initdo |config|
config.dsn="http://key@sentry.localdomain/42"config.environment="test"config.enabled_environments=["test"]end# Test A: first sentry testsetup_sentry_testteardown_sentry_test# Test B: intermediate request (no sentry helper)Sentry.clone_hub_to_current_threadSentry.capture_message("leaked event from test B")puts"main_hub transport events: #{Sentry.get_main_hub.current_client.transport.events.count}"# => 1# Test C: new sentry test (should start clean)setup_sentry_testputs"sentry_events (thread-local): #{sentry_events.count}"# => 0 (looks clean)# Simulate Rack middlewareSentry.clone_hub_to_current_threadputs"sentry_events (after clone): #{Sentry.get_current_client.transport.events.count}"# => 1 (BUG: stale event from Test B leaked through!)teardown_sentry_test
After setup_sentry_test, sentry_events should always be empty, even after clone_hub_to_current_thread is called.
Root Cause
setup_sentry_test calls get_current_hub which returns the thread-local hub (not necessarily @main_hub)
It modifies this hub with DummyTransport
clone_hub_to_current_thread always clones @main_hub, discarding the thread-local hub
Hub#clone creates Hub.new(layer.client, scope.dup) — sharing the same client (and transport) as @main_hub
Stale events on @main_hub's DummyTransport become visible through the clone
Workaround
DummyTransport (as of sentry-ruby 6.5.0) does not implement clear, so events and envelopes arrays must be cleared directly on both the current hub and @main_hub transports:
defclear_sentry_transport(transport)returnunlesstransporttransport.events.cleariftransport.respond_to?(:events)transport.envelopes.cleariftransport.respond_to?(:envelopes)end# After setup_sentry_test:clear_sentry_transport(Sentry.get_current_client&.transport)clear_sentry_transport(Sentry.get_main_hub&.current_client&.transport)
Both hubs must be cleared because clone_hub_to_current_thread shares the same client (and transport) instance between @main_hub and its clones via Hub#clone.
Activity
linear-code commentedon May 13, 2026
RUBY-178
solnic commentedon May 18, 2026
Thanks for reporting this! I'm gonna get it fixed 😄
test(test_helper): add failing regression specs for clone_hub event l…
feat(test_helper): add DummyTransport#clear to empty captured events
fix(test_helper): anchor setup/teardown to the main hub (#2951)
test(test_helper): add Rack two-request leak regression spec (#2951)
refactor(test_helper): use public Hub#clients instead of @stack ivar (#…
test(test_helper): add failing regression specs for clone_hub event l…
feat(test_helper): add DummyTransport#clear to empty captured events
fix(test_helper): anchor setup/teardown to the main hub (#2951)
test(test_helper): add Rack two-request leak regression spec (#2951)
refactor(test_helper): use public Hub#clients instead of @stack ivar (#…
fix(tests): proper dummy transport clean up for hub cloning (#2957)