From 5a2439c4083431538af795ac9fa42fb878f2a8e4 Mon Sep 17 00:00:00 2001 From: "posthog[bot]" <206114724+posthog[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 02:03:10 +0000 Subject: [PATCH] fix: accept kwargs in capture_exception so $exception_fingerprint is preserved The positional-only signature silently dropped custom properties when users called capture_exception with the kwargs convention used elsewhere in the SDK (distinct_id:, properties:). This broke documented Error Tracking features like custom exception grouping via $exception_fingerprint. Now accepts both forms; existing positional callers are unaffected. Generated-By: PostHog Code Task-Id: 6a34588b-65e0-4139-80eb-913a2d82829a --- lib/posthog/client.rb | 13 ++++++++++++- posthog-rails/README.md | 11 +++++++++-- spec/posthog/client_spec.rb | 25 +++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/lib/posthog/client.rb b/lib/posthog/client.rb index 2f8cd9f..c3e9628 100644 --- a/lib/posthog/client.rb +++ b/lib/posthog/client.rb @@ -222,10 +222,21 @@ def capture(attrs) # Captures an exception as an event # + # Supports both positional and keyword argument styles: + # capture_exception(exception, 'user-123', { '$exception_fingerprint' => 'CustomGroup' }) + # capture_exception(exception, distinct_id: 'user-123', properties: { '$exception_fingerprint' => 'CustomGroup' }) + # # @param [Exception, String, Object] exception The exception to capture, a string message, or exception-like object # @param [String] distinct_id The ID for the user (optional, defaults to a generated UUID) # @param [Hash] additional_properties Additional properties to include with the exception event (optional) - def capture_exception(exception, distinct_id = nil, additional_properties = {}) + # @param [Hash] kwargs Keyword form: :distinct_id, :properties + def capture_exception(exception, distinct_id = nil, additional_properties = nil, **kwargs) + unless kwargs.empty? + distinct_id = kwargs[:distinct_id] if distinct_id.nil? + additional_properties = kwargs[:properties] if additional_properties.nil? + end + additional_properties ||= {} + exception_info = ExceptionCapture.build_parsed_exception(exception) return if exception_info.nil? diff --git a/posthog-rails/README.md b/posthog-rails/README.md index c5b906b..edab2a3 100644 --- a/posthog-rails/README.md +++ b/posthog-rails/README.md @@ -131,9 +131,16 @@ PostHog.identify( # Track an exception manually PostHog.capture_exception( exception, - current_user.id, - { custom_property: 'value' } + distinct_id: current_user.id, + properties: { + custom_property: 'value', + # Override exception grouping by setting a fingerprint + '$exception_fingerprint' => 'CustomExceptionGroup' + } ) + +# The positional form is still supported: +# PostHog.capture_exception(exception, current_user.id, { custom_property: 'value' }) ``` ### Background Jobs diff --git a/spec/posthog/client_spec.rb b/spec/posthog/client_spec.rb index 62a7c91..3719b6d 100644 --- a/spec/posthog/client_spec.rb +++ b/spec/posthog/client_spec.rb @@ -1347,6 +1347,31 @@ def run expect(message[:distinct_id].length).to eq(36) expect(message[:properties]['$process_person_profile']).to be false end + + it 'captures exception via kwargs with $exception_fingerprint' do + begin + raise StandardError, 'Test exception' + rescue StandardError => e + client.capture_exception( + e, + distinct_id: 'user-123', + properties: { + '$exception_fingerprint' => 'CustomExceptionGroup', + 'user_agent' => 'Test Agent' + } + ) + end + + message = client.dequeue_last_message + + expect(message[:event]).to eq('$exception') + expect(message[:distinct_id]).to eq('user-123') + expect(message[:properties]['$exception_list'].first['type']).to eq('StandardError') + expect(message[:properties]['$exception_list'].first['value']).to eq('Test exception') + expect(message[:properties]['$exception_fingerprint']).to eq('CustomExceptionGroup') + expect(message[:properties]['user_agent']).to eq('Test Agent') + expect(message[:properties]).not_to have_key('$process_person_profile') + end end context 'common' do