Skip to content

fix(android): Prevent breadcrumb loss from numeric timestamp ClassCastException#6308

Merged
antonis merged 2 commits into
mainfrom
fix/android-breadcrumb-timestamp
Jun 18, 2026
Merged

fix(android): Prevent breadcrumb loss from numeric timestamp ClassCastException#6308
antonis merged 2 commits into
mainfrom
fix/android-breadcrumb-timestamp

Conversation

@antonis

@antonis antonis commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

On Android, every breadcrumb synced from JS to the native scope was being discarded since 8.14.0.

The JS SDK stamps breadcrumb.timestamp as a number (epoch seconds), which arrives over the bridge as a java.lang.Double. Since #6261, RNSentryBreadcrumb.fromMap feeds the map to the native Breadcrumb.Deserializer, which reads timestamp via MapObjectReader.nextDateOrNullnextStringOrNull and requires an ISO-8601 string. A Double throws ClassCastException, the breadcrumb is dropped, and an empty fallback (only origin = "react-native") is returned — so native/tombstone crash reports lose breadcrumb context.

java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.String
	at io.sentry.util.MapObjectReader.nextStringOrNull(MapObjectReader.java:321)
	at io.sentry.util.MapObjectReader.nextDateOrNull(MapObjectReader.java:146)
	at io.sentry.Breadcrumb$Deserializer.deserialize(Breadcrumb.java:872)
	at io.sentry.react.RNSentryBreadcrumb.fromMap(RNSentryBreadcrumb.java:47)

This PR normalizes a numeric timestamp to an ISO-8601 string before deserializing, preserving millisecond precision. Existing behavior is unchanged for ISO-string and missing timestamps. iOS is unaffected (Cocoa's initWithDictionary: is lenient).

💡 Motivation and Context

Fixes #6306. Regression introduced in 8.14.0 by #6261 ("Use native SDK deserializers for User and Breadcrumb").

💚 How did you test it?

Added RNSentryBreadcrumbTest.parsesNumericTimestampWithoutDiscardingBreadcrumb, which feeds a numeric timestamp and asserts the breadcrumb survives with its fields and correct timestamp. Verified it fails (message is null) without the fix and passes with it. Full Android unit suite green.

📝 Checklist

  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing
  • No breaking changes

🔮 Next steps

A follow-up PR will fix a separate, pre-existing issue surfaced during this investigation: user geo is JSON-stringified before crossing the bridge, so the native deserializer drops it (and on Android, the whole user). That fix touches the JS layer and coordinates with #6289.

…tException

The JS SDK stamps `breadcrumb.timestamp` as a number (epoch seconds), which
arrives over the bridge as a `Double`. Since 8.14.0 (#6261) the native
`Breadcrumb.Deserializer` reads `timestamp` as an ISO-8601 string and threw a
`ClassCastException`, discarding every synced breadcrumb on Android so native
crash reports lost breadcrumb context.

Normalize a numeric `timestamp` to an ISO-8601 string before deserializing.

Fixes #6306

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • fix(android): Prevent breadcrumb loss from numeric timestamp ClassCastException by antonis in #6308
  • chore(deps): update CLI to v3.5.1 by github-actions in #6305
  • chore(deps): update JavaScript SDK to v10.58.0 by github-actions in #6296
  • chore: Fix lint issues by antonis in #6300
  • chore: Bump sample and perf test apps to React Native 0.86.0 by antonis in #6287
  • fix(deps): bump form-data from 4.0.5 to 4.0.6 by antonis in #6297
  • fix(ci): Handle @sentry-internal/* package renames in JS updater by antonis in #6295
  • Record network request/response bodies in Session Replay by alwx in #6288
  • chore(deps): bump tar from 7.5.11 to 7.5.16 by dependabot in #6293
  • fix(ci): Update renamed @sentry-internal/* packages in JS updater script by antonis in #6294
  • chore(deps): bump launch-editor from 2.11.1 to 2.14.1 by dependabot in #6291
  • chore(deps-dev): bump @babel/core from 7.26.7 to 7.29.6 by dependabot in #6292
  • fix(deps): Resolve shell-quote to >=1.8.4 (Dependabot RNSentryModule.captureEvent is ignoring environment #547) by antonis in #6286
  • fix(ci): Support version catalog in android SDK version check by antonis in #6280
  • test(e2e): Bump E2E tests to React Native 0.86.0 by antonis in #6268
  • feat(android): Add nativeStackAndroid support to NativeLinkedErrors by lucas-zimerman in #6278
  • chore(deps): bump ruby/setup-ruby from 1.310.0 to 1.313.0 by dependabot in #6282
  • chore(deps): update Maestro to v2.6.1 by github-actions in #6277
  • chore(deps): bump gradle/actions from 6.1.0 to 6.2.0 by dependabot in #6284
  • chore(deps): bump getsentry/craft from 2.26.8 to 2.26.10 by dependabot in #6283
  • chore(deps): bump getsentry/craft/.github/workflows/changelog-preview.yml from 2.26.8 to 2.26.10 by dependabot in #6281
  • chore(deps): update Sentry Android Gradle Plugin to v6.11.0 by github-actions in #6275
  • chore(deps): update Android SDK to v8.43.2 by github-actions in #6273
  • chore(deps): bump joi from 17.13.3 to 17.13.4 by dependabot in #6279

Plus 3 more


🤖 This preview updates automatically when you update the PR.

Comment thread CHANGELOG.md Outdated
@antonis

antonis commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@sentry review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit a8c2748. Configure here.

@sentry

sentry Bot commented Jun 17, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
Sentry RN io.sentry.reactnative.sample 8.14.0 (91) Release

⚙️ sentry-react-native Build Distribution Settings

@antonis antonis marked this pull request as ready for review June 17, 2026 14:09
@github-actions

Copy link
Copy Markdown
Contributor

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 415.71 ms 453.50 ms 37.79 ms
Size 49.74 MiB 54.79 MiB 5.05 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
4e0ba9c+dirty 452.84 ms 473.36 ms 20.52 ms
5748023+dirty 446.69 ms 505.63 ms 58.94 ms
bc0d8cf+dirty 412.37 ms 466.26 ms 53.89 ms
3817909+dirty 406.67 ms 416.58 ms 9.91 ms
0bd8916+dirty 412.77 ms 451.31 ms 38.54 ms
68672fc+dirty 425.02 ms 487.56 ms 62.54 ms
2c735cc+dirty 414.09 ms 438.47 ms 24.38 ms
6176a94+dirty 410.90 ms 452.20 ms 41.31 ms
37a2091+dirty 407.82 ms 441.22 ms 33.40 ms
5a21b51+dirty 471.42 ms 524.22 ms 52.80 ms

App size

Revision Plain With Sentry Diff
4e0ba9c+dirty 48.30 MiB 53.49 MiB 5.19 MiB
5748023+dirty 48.30 MiB 53.54 MiB 5.23 MiB
bc0d8cf+dirty 48.30 MiB 53.48 MiB 5.18 MiB
3817909+dirty 43.75 MiB 48.08 MiB 4.33 MiB
0bd8916+dirty 48.30 MiB 53.57 MiB 5.26 MiB
68672fc+dirty 48.30 MiB 53.61 MiB 5.31 MiB
2c735cc+dirty 43.75 MiB 48.08 MiB 4.33 MiB
6176a94+dirty 48.30 MiB 53.54 MiB 5.24 MiB
37a2091+dirty 48.30 MiB 53.58 MiB 5.28 MiB
5a21b51+dirty 48.30 MiB 53.49 MiB 5.19 MiB

@github-actions

Copy link
Copy Markdown
Contributor

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 433.04 ms 489.72 ms 56.68 ms
Size 49.74 MiB 54.79 MiB 5.05 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
4e0ba9c+dirty 421.39 ms 455.80 ms 34.41 ms
5748023+dirty 413.71 ms 468.71 ms 54.99 ms
890d145+dirty 486.42 ms 514.85 ms 28.43 ms
0bd8916+dirty 400.15 ms 442.72 ms 42.57 ms
68672fc+dirty 407.55 ms 442.96 ms 35.41 ms
6176a94+dirty 403.58 ms 446.73 ms 43.15 ms
37a2091+dirty 429.71 ms 477.00 ms 47.29 ms
5a21b51+dirty 505.16 ms 539.20 ms 34.04 ms
bc0d8cf+dirty 407.66 ms 461.35 ms 53.69 ms
c823bb5+dirty 468.26 ms 516.16 ms 47.90 ms

App size

Revision Plain With Sentry Diff
4e0ba9c+dirty 48.30 MiB 53.49 MiB 5.19 MiB
5748023+dirty 48.30 MiB 53.54 MiB 5.23 MiB
890d145+dirty 43.94 MiB 49.00 MiB 5.06 MiB
0bd8916+dirty 48.30 MiB 53.57 MiB 5.26 MiB
68672fc+dirty 48.30 MiB 53.61 MiB 5.31 MiB
6176a94+dirty 48.30 MiB 53.54 MiB 5.24 MiB
37a2091+dirty 48.30 MiB 53.58 MiB 5.28 MiB
5a21b51+dirty 48.30 MiB 53.49 MiB 5.19 MiB
bc0d8cf+dirty 48.30 MiB 53.48 MiB 5.18 MiB
c823bb5+dirty 48.30 MiB 53.58 MiB 5.28 MiB

@alwx alwx 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.

dw

@antonis antonis merged commit 7887847 into main Jun 18, 2026
125 of 135 checks passed
@antonis antonis deleted the fix/android-breadcrumb-timestamp branch June 18, 2026 09:04
@tomekzaw

Copy link
Copy Markdown

Thanks for the fix! 🚀

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

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Android: breadcrumb sync throws ClassCastException (Double cannot be cast to String) since 8.14.0

3 participants