Repository navigation
fix(replay): Accept Double timestamps in Android network breadcrumb conversion - #3859
Conversation
…onversion Since 9.21.0 breadcrumbs are synced to Android as JSON bytes and re-parsed by sentry-java, whose JsonObjectDeserializer parses epoch-millisecond values as Double (they overflow Integer, and nextDouble() is tried before nextLong()). The unchecked 'as Long' cast in convertNetworkBreadcrumb then threw ClassCastException for every http breadcrumb, failing replay segment creation and breaking Session Replay on Android. Accept any Number for start/end_timestamp and skip the event when fields are missing or mistyped, matching the iOS converter behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3859 +/- ##
==========================================
+ Coverage 87.35% 91.50% +4.15%
==========================================
Files 338 105 -233
Lines 12283 3803 -8480
==========================================
- Hits 10730 3480 -7250
+ Misses 1553 323 -1230
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
|
hey, sorry in advance that this PR is not impeccable, I've been looking into this problem with the help of Claude then asked if he "can fix it and create a PR" theoretically, but he actually went full throttle 😬 The problem is real and the fix should be working too, but I am going to manually review and test everything now |
|
@aqrc thx! ignore the CI failures, the e2e test is not running due to missing auth permissions since it's a fork |
|
I reviewed the code - looks legit to me, only questionable thing is the comment (it is up to you to keep it or to remove it). I also imported the fix into a real app and I confirm that Replay works correctly now. |
📜 Description
Fixes Session Replay being broken on Android since
9.21.0: replays were either missing entirely or uploaded as short glitchy fragments.SentryFlutterReplayBreadcrumbConverter.convertNetworkBreadcrumbcaststart_timestamp/end_timestampwith an uncheckedas Long. Since #3708, breadcrumbs are synced to Android as JSON bytes and re-parsed by sentry-java'sBreadcrumb.Deserializer, whoseJsonObjectDeserializer.nextNumber()triesnextInt()→nextDouble()→nextLong(). Epoch-millisecond values overflowInteger, so they are parsed asDoubleandnextLong()is never reached. The cast then threw for everyhttpbreadcrumb:Because the exception is thrown inside replay segment creation, any segment containing an
httpbreadcrumb was dropped — in apps with regular network traffic this effectively disables Session Replay on Android.This change accepts any
Numberfor the timestamps and returnsnullwhenurlor the timestamps are missing or mistyped instead of throwing, matching what the iOS converter (convertNetwork:inSentryFlutterReplayBreadcrumbConverter.m) already does with itsisKindOfClass:guards.💡 Motivation and Context
Replay worked on
9.20.0(typed method-channel scope sync preservedLong) and broke on9.21.0+ for Android. The same numeric-subtype issue was fixed in sentry-react-native's converter in getsentry/sentry-react-native#6288.💚 How did you test it?
ClassCastExceptionagainst the unmodified converter by invokingconvert()with anhttpbreadcrumb whosestart_timestamp/end_timestampareDouble(compiled againstsentry-android 8.47.0).Doubletimestamps →RRWebSpanEventwith correct second-precision start/end timestampsLongtimestamps (pre-9.21 path) → unchanged behaviorurlor non-numeric timestamp → returnsnullinstead of throwingktlintpasses.📝 Checklist
sendDefaultPiiis enabled🔮 Next steps
The root cause — sentry-java's
JsonObjectDeserializer.nextNumber()returningDoublefor any value that overflowsInteger— may affect other consumers of JSON-synced scope data and could be worth fixing upstream in sentry-java as well.🤖 Generated with Claude Code