Android: turbo_module.* crash tags permanently pinned to RNSentry.initNativeReactNavigationNewFrameTracking (promise never settles)
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 78/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- android, react-native, typescript
- Lĩnh vực
- mobile
Hướng nghiên cứu
Đọc android/src/main/java/io/sentry/react/RNSentryModuleImpl.java và so sánh initNativeReactNavigationNewFrameTracking với phần triển khai iOS trong ios/RNSentry.mm. Kiểm tra cách các phương thức trả về Promises được xử lý trong src/js/turbomodule/wrapTurboModule.ts; issue cũng đề xuất kiểm tra các phương thức khác nhận Promises trong RNSentryModuleImpl. Hoàn thành khi lệnh gọi này không còn khiến một tracker frame bị mắc kẹt và hành vi trên Android phù hợp với việc Promise được settle như dự kiến.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
On Android, the crash-time TurboModule attribution added in #6227 is permanently pinned to a single startup call. Every native crash report from an Android app carries:
turbo_module.name: RNSentry
turbo_module.method: initNativeReactNavigationNewFrameTracking
regardless of what was actually executing. The tags are not stale-by-a-moment; they are stuck for the entire process lifetime, so the feature reports a wrong answer rather than no answer. iOS is unaffected.
Cause
Three facts compose:
-
wrapTurboModulepops a tracker frame for a promise-returning method only when that promise settles (src/js/turbomodule/wrapTurboModule.ts— theisThenable(result)branch pops in boththenhandlers). -
The Android implementation never settles the promise:
// android/src/main/java/io/sentry/react/RNSentryModuleImpl.java public void initNativeReactNavigationNewFrameTracking(Promise promise) { this.initFragmentInitialFrameTracking(); }promiseis accepted and dropped — noresolve, noreject, no path that settles it later. iOS does the equivalent work and then callsresolve(nil)(ios/RNSentry.mm). -
RNSENTRY_SKIPinturboModuleContextIntegrationdoes not include this method, so it is wrapped like any other.
The frame pushed at startup therefore never pops. popTurboModuleCall walks the stack and re-syncs the scope onto "the newest remaining frame on the same scope" after every subsequent pop — which, once the app is idle, is always the leaked startup frame. The native scope is left holding it, and sentry-java serialises it into every crash report.
Two smaller consequences of the same leak: the tracker stack never drains to empty (so clearScope's empty-string sentinel path is unreachable on Android), and the aggregate record for that call is never emitted.
Steps to reproduce
- Expo app on Android with
enableTimeToInitialDisplayon (expoRouterIntegrationorreactNavigationIntegration). - Let the app finish starting, navigate anywhere, idle.
- Trigger any native crash — e.g.
Sentry.nativeCrash()— or readgetTurboModuleCallStack(). - The event's tags report
RNSentry.initNativeReactNavigationNewFrameTrackingas the in-flight call; the stack still holds that frame.
Suggested fix
Settle the promise in the Android implementation, mirroring iOS:
public void initNativeReactNavigationNewFrameTracking(Promise promise) {
this.initFragmentInitialFrameTracking();
promise.resolve(null);
}
Adding the method to RNSENTRY_SKIP would hide the symptom but leave the dangling promise, so the native-side fix seems the right one. It may be worth auditing the other Promise-taking methods in RNSentryModuleImpl for the same shape.
Versions
@sentry/react-native: reproduced on 8.27.0; the Android code is unchanged on 8.29.0 (current latest)- Platform: Android only (iOS resolves correctly)
- Ngôn ngữ chính
- TypeScript
- Star
- 1.8k
- Fork
- 369
- Merge trung bình
- 23 giờ 19 phút
- Pull request đã merge (30 ngày)
- 113
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của getsentry/sentry-react-native
-
React-Native Replays Task
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
getsentry/sentry-react-native#6680 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Improvement React-Native
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
getsentry/sentry-react-native#6143 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
React-Native Task User Feedbacks
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
getsentry/sentry-react-native#5932 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
React-Native Replays Task
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
getsentry/sentry-react-native#5882 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Good First Issue React-Native Task
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 65/100
getsentry/sentry-react-native#5771 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của getsentry/sentry-react-native
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
vercel/streamdown#673 · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
docs(stream-protocol): document messageMetatadata on start/finish and the message-metadata chunkĐang mởfactory-active task-identify-harness-labels-done task-identify-issue-type-done
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
vercel/ai#23375 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
agilepathway/label-checker#721 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
CLI Empathy needs triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
chromaui/chromatic-cli#1524 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày