Skip to content

fix: serialize non-finite event properties as null - #315

Merged
marandaneto merged 2 commits into
mainfrom
fix/non-finite-event-properties-20261022
Oct 22, 2026
Merged

marandaneto merged 2 commits into
mainfrom
fix/non-finite-event-properties-20261022

Conversation

@marandaneto

@marandaneto marandaneto commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

💡 Motivation and Context

Events containing numeric NaN or positive/negative Infinity can be lost during serialization. This also affects nested objects and arrays in synchronous and background delivery.

Normalize these numbers to JSON null in MessageBatch without mutating caller containers. Keep array positions, valid neighboring events and unsupported serializer errors intact.

Include explicit patch changesets for both posthog-ruby and posthog-rails, so the Rails release requires the core SDK fix.

Related Python work: PostHog/posthog-python#1081. This is context, not a claim that the Python PR is merged.

💚 How did you test it?

Verified expected failures before the fix and passing strict JSON payloads afterward through actual capture and mocked HTTP responses. Tests cover all three numbers, nested maps and arrays, input preservation, literal strings, valid neighbors, dates and SDK metadata. Isolated compatibility tests cover JSON, ActiveSupport, Oj and both together.

232 focused examples passed. The full default suite passed 1558 examples with two optional OTel integrations pending. RuboCop, the public API snapshot and both gem builds passed. The signed final commit passed branch autoreview with no actionable findings.

Local validation used Ruby 4.0.7. The CI Ruby matrix and optional OTel integrations were not run locally.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed. (No documentation change needed.)
  • No breaking change or entry added to the changelog. (Patch changeset included.)

If releasing new changes

  • Ran pnpm changeset to generate a changeset file

Patch changesets were authored manually in .changeset/tidy-numbers-travel.md and .changeset/quiet-rails-numbers.md. The validated release plan includes patch releases for both gems.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Human DRI: @marandaneto. Implemented with the Pi implementation agent using local shell/Ruby tools. The approved policy converts non-finite Float values to null while preserving caller containers and existing unsupported serializer errors. Pi branch autoreview found no actionable issues. Human review is required.

@marandaneto marandaneto self-assigned this Oct 22, 2026
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

posthog-ruby-async Compliance Report

Date: 2026-10-22T13:36:44.057682+00:00
Duration: 98211ms

⚠️ Some Tests Failed

46/47 tests passed, 1 failed


Capture Tests

✅ 30/30 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 7ms
Format Validation.Event Has Uuid ✅ 105ms
Format Validation.Event Has Lib Properties ✅ 107ms
Format Validation.Distinct Id Is String ✅ 106ms
Format Validation.Token Is Present ✅ 105ms
Format Validation.Custom Properties Preserved ✅ 106ms
Format Validation.Event Has Timestamp ✅ 106ms
Format Validation.Non Utc Event Timestamp Is Converted To Utc ✅ 8ms
Retry Behavior.Retries On 503 ✅ 5410ms
Retry Behavior.Does Not Retry On 400 ✅ 2107ms
Retry Behavior.Does Not Retry On 401 ✅ 2107ms
Retry Behavior.Respects Retry After Header ✅ 8115ms
Retry Behavior.Implements Backoff ✅ 15521ms
Retry Behavior.Retries On 500 ✅ 5211ms
Retry Behavior.Retries On 502 ✅ 5208ms
Retry Behavior.Retries On 504 ✅ 5211ms
Retry Behavior.Max Retries Respected ✅ 15621ms
Deduplication.Generates Unique Uuids ✅ 109ms
Deduplication.Preserves Uuid On Retry ✅ 5210ms
Deduplication.Preserves Uuid And Timestamp On Retry ✅ 10415ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 5214ms
Deduplication.No Duplicate Events In Batch ✅ 110ms
Deduplication.Different Events Have Different Uuids ✅ 106ms
Compression.Sends Gzip When Enabled ✅ 105ms
Batch Format.Uses Proper Batch Structure ✅ 104ms
Batch Format.Flush With No Events Sends Nothing ✅ 4ms
Batch Format.Multiple Events Batched Together ✅ 108ms
Error Handling.Does Not Retry On 403 ✅ 2107ms
Error Handling.Does Not Retry On 413 ✅ 2108ms
Error Handling.Retries On 408 ✅ 5210ms

Feature_Flags Tests

⚠️ 16/17 tests passed, 1 failed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 107ms
Request Payload.Flags Request Uses V2 Query Param ✅ 105ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 106ms
Request Payload.Flags Request Omits Authorization Header ✅ 107ms
Request Payload.Token In Flags Body Matches Init ✅ 106ms
Request Payload.Groups Round Trip ✅ 107ms
Request Payload.Groups Default To Empty Object ✅ 105ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 106ms
Request Payload.Disable Geoip Omitted Defaults To False ❌ 105ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 105ms
Request Lifecycle.No Flags Request On Init Alone ✅ 2ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 105ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 108ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 106ms
Retry Behavior.Retries Flags On 502 ✅ 233ms
Retry Behavior.Retries Flags On 504 ✅ 207ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 107ms

Failures

request_payload.disable_geoip_omitted_defaults_to_false

Field 'geoip_disable' not found in /flags request body at path 'geoip_disable'. Available keys: ['distinct_id', 'groups', 'person_properties', 'group_properties', 'flag_keys_to_evaluate', 'token']

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

posthog-ruby-sync Compliance Report

Date: 2026-10-22T13:36:34.505682+00:00
Duration: 94219ms

⚠️ Some Tests Failed

45/47 tests passed, 2 failed


Capture Tests

⚠️ 29/30 tests passed, 1 failed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 10ms
Format Validation.Event Has Uuid ✅ 7ms
Format Validation.Event Has Lib Properties ✅ 6ms
Format Validation.Distinct Id Is String ✅ 10ms
Format Validation.Token Is Present ✅ 7ms
Format Validation.Custom Properties Preserved ✅ 7ms
Format Validation.Event Has Timestamp ✅ 8ms
Format Validation.Non Utc Event Timestamp Is Converted To Utc ✅ 7ms
Retry Behavior.Retries On 503 ✅ 5310ms
Retry Behavior.Does Not Retry On 400 ✅ 2011ms
Retry Behavior.Does Not Retry On 401 ✅ 2011ms
Retry Behavior.Respects Retry After Header ✅ 8017ms
Retry Behavior.Implements Backoff ✅ 15268ms
Retry Behavior.Retries On 500 ✅ 5142ms
Retry Behavior.Retries On 502 ✅ 5160ms
Retry Behavior.Retries On 504 ✅ 5153ms
Retry Behavior.Max Retries Respected ✅ 15573ms
Deduplication.Generates Unique Uuids ✅ 22ms
Deduplication.Preserves Uuid On Retry ✅ 5155ms
Deduplication.Preserves Uuid And Timestamp On Retry ✅ 10304ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 5154ms
Deduplication.No Duplicate Events In Batch ✅ 21ms
Deduplication.Different Events Have Different Uuids ✅ 9ms
Compression.Sends Gzip When Enabled ✅ 7ms
Batch Format.Uses Proper Batch Structure ✅ 7ms
Batch Format.Flush With No Events Sends Nothing ✅ 4ms
Batch Format.Multiple Events Batched Together ❌ 17ms
Error Handling.Does Not Retry On 403 ✅ 2008ms
Error Handling.Does Not Retry On 413 ✅ 2011ms
Error Handling.Retries On 408 ✅ 5116ms

Failures

batch_format.multiple_events_batched_together

Expected 1 requests, got 5

Feature_Flags Tests

⚠️ 16/17 tests passed, 1 failed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 11ms
Request Payload.Flags Request Uses V2 Query Param ✅ 8ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 9ms
Request Payload.Flags Request Omits Authorization Header ✅ 7ms
Request Payload.Token In Flags Body Matches Init ✅ 7ms
Request Payload.Groups Round Trip ✅ 6ms
Request Payload.Groups Default To Empty Object ✅ 7ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 7ms
Request Payload.Disable Geoip Omitted Defaults To False ❌ 7ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 6ms
Request Lifecycle.No Flags Request On Init Alone ✅ 3ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 6ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 10ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 7ms
Retry Behavior.Retries Flags On 502 ✅ 139ms
Retry Behavior.Retries Flags On 504 ✅ 110ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 9ms

Failures

request_payload.disable_geoip_omitted_defaults_to_false

Field 'geoip_disable' not found in /flags request body at path 'geoip_disable'. Available keys: ['distinct_id', 'groups', 'person_properties', 'group_properties', 'flag_keys_to_evaluate', 'token']

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PostHog Review · Standard · reviewed 88a4713: no findings.

This Standard review started from the posthog-review label. Comment @posthog review --deep for a Deep review, or @posthog help to see all commands.

@posthog posthog Bot removed the reviewhog label Oct 22, 2026
@marandaneto
marandaneto marked this pull request as ready for review October 22, 2026 13:29
@marandaneto
marandaneto requested a review from a team as a code owner October 22, 2026 13:29
@posthog posthog Bot removed the reviewhog label Oct 22, 2026
@marandaneto
marandaneto merged commit 23134c3 into main Oct 22, 2026
24 checks passed
@marandaneto
marandaneto deleted the fix/non-finite-event-properties-20261022 branch October 22, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants