Repository navigation
Android: breadcrumb sync throws ClassCastException (Double cannot be cast to String) since 8.14.0 #6306
Description
What React Native libraries do you use?
Hermes, RN New Architecture, Expo (mobile only), Expo Router
Are you using sentry.io or on-premise?
sentry.io (SaS)
Are you using any other error monitoring solution alongside Sentry?
No
@sentry/react-native SDK Version
8.13.0 → 8.14.0 (regression introduced in 8.14.0)
How does your development environment look like?
- macOS, Android (issue is Android-only; iOS is unaffected)
- React Native 0.85.3, Hermes + New Architecture enabled
- Expo SDK 56, Expo Router
Sentry.init()
Sentry.init({
dsn: "https://...@o...ingest.de.sentry.io/...",
enabled: !__DEV__,
environment: "production",
enableTombstone: true,
integrations: [Sentry.reactNavigationIntegration()],
});Steps to Reproduce
- Use
@sentry/react-native@8.14.0on Android. - Add any breadcrumb from JS — either manually (
Sentry.addBreadcrumb({ message: "test" })) or via auto-instrumentation (navigation, console, etc.). The JS scope syncs it to the native scope viaRNSentry.addBreadcrumb. - Watch Logcat.
Expected Result
The breadcrumb is added to the native Android scope (with its message/category/data/timestamp), so it appears in native/tombstone crash reports. No error logged.
Actual Result
RNSentryBreadcrumb.fromMap logs an error and discards the breadcrumb, returning an empty fallback breadcrumb (only origin = "react-native"). The breadcrumb is lost from the native scope, so native crash reports lose breadcrumb context. Logcat (one entry per breadcrumb):
Failed to deserialize breadcrumb from map.
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)
at io.sentry.react.RNSentryModuleImpl.lambda$addBreadcrumb$5(RNSentryModuleImpl.java:614)
at io.sentry.react.RNSentryModuleImpl$$ExternalSyntheticLambda5.run(D8$$SyntheticClass:0)
at io.sentry.Scopes.configureScope(Scopes.java:753)
at io.sentry.Sentry.configureScope(Sentry.java:1121)
at io.sentry.Sentry.configureScope(Sentry.java:1111)
at io.sentry.react.RNSentryModuleImpl.addBreadcrumb(RNSentryModuleImpl.java:612)
at io.sentry.react.RNSentryModule.addBreadcrumb(RNSentryModule.java:98)
at com.facebook.jni.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:1095)
at android.os.Handler.dispatchMessageImpl(Handler.java:135)
at android.os.Handler.dispatchMessage(Handler.java:125)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.kt:21)
at android.os.Looper.loopOnce(Looper.java:296)
at android.os.Looper.loop(Looper.java:397)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$Companion.startNewBackgroundThread$lambda$0(MessageQueueThreadImpl.kt:152)
at java.lang.Thread.run(Thread.java:1572)
Root cause
The JS SDK (@sentry/core) stamps breadcrumb.timestamp as a number (epoch seconds) and forwards it unchanged to native (scopeSync → wrapper.addBreadcrumb → RNSentry.addBreadcrumb). Over the bridge it becomes a java.lang.Double.
On Android, RNSentryBreadcrumb.fromMap now feeds that map to the wire-format Breadcrumb.Deserializer, which reads timestamp via MapObjectReader.nextDateOrNull → nextStringOrNull and requires an ISO-8601 string, so a Double throws ClassCastException.
This was introduced by #6261 ("Use native SDK deserializers for User and Breadcrumb"), first shipped in 8.14.0. Before that, fromMap parsed fields manually and ignored the numeric timestamp, so it didn't crash. iOS is unaffected because it uses the Cocoa SDK's lenient initWithDictionary:.
Note: User was migrated to the same deserializer in #6261, so its date/numeric fields may have the same issue.
Workaround
Normalize the numeric timestamp to an ISO-8601 string in fromMap before deserializing:
final Map<String, Object> map = toDeepHashMap(from);
final Object timestamp = map.get("timestamp");
if (timestamp instanceof Number) {
map.put("timestamp",
io.sentry.DateUtils.getTimestamp(new java.util.Date((long) (((Number) timestamp).doubleValue() * 1000))));
}
final MapObjectReader reader = new MapObjectReader(map);Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsNo status
Activity
linear-code commentedon Jun 17, 2026
RN-677
antonis commentedon Jun 17, 2026
Thank you for reporting 🙇 We are working on a fix in #6308
We will iterate here one the fix is shipped.
fix(android): Prevent breadcrumb loss from numeric timestamp ClassCas…
github-actions commentedon Jun 18, 2026
A PR closing this issue has just been released 🚀
This issue was referenced by PR #6308, which was included in the 8.15.0 release.