Description
When enableTombstone is enabled in a Flutter Android app, a native SIGSEGV crash is reported as a TombstoneMerged event. Compared with the regular native signalhandler event for the same crash, the merged tombstone event no longer contains the app native library debug image in debugmeta.images, so Sentry cannot symbolicate the app frame to the source file and line.
The regular native crash resolves to native_crash.cpp, but the TombstoneMerged event only shows the JNI symbol/address.
Expected behavior
The merged tombstone event should preserve enough native debug image information from the original native SDK event, or include the app native library image parsed from the tombstone, so the app frame can still be symbolicated to source file and line.
Actual behavior
Regular native crash event (mechanism=signalhandler) is symbolicated:
- Event ID:
a0fc8e59e5a84631746cfb62af3cf072
- SDK:
sentry.native.android.flutter 0.14.2
- App native debug image is present and found:
- debug id:
2387c138-d607-9c92-9829-9c0adb12b9fd
- status:
found
has_debug_info=true, has_sources=true, has_symbols=true, has_unwind_info=true
- Top app frame resolves to:
- function:
Java_com_example_sentry_1demo_MainActivity_triggerNativeSegfault
- file:
native_crash.cpp
- path:
android/app/src/main/cpp/native_crash.cpp
Tombstone merged event is not symbolicated to source file/line:
- Event ID:
ba490da4525e4ec519f0fbf27c1966be
- SDK:
sentry.native.android.flutter 0.15.2
- mechanism:
TombstoneMerged
- Crashing app frame is shown as:
base.apk!libsentry_demo_native.so 0x79e0279618 Java_com_example_sentry_1demo_MainActivity_triggerNativeSegfault
- The event does not include the app native debug image
2387c138-d607-9c92-9829-9c0adb12b9fd in debugmeta.images.
- Missing images are mostly Android system/ART/OAT files, for example
boot.oat, boot-framework.oat, libc.so, libandroid_runtime.so.
Relevant debugmeta comparison
Regular signalhandler event includes the app native image and Sentry finds uploaded symbols:
{
"type": "elf",
"code_file": "/data/app/.../base.apk",
"debug_id": "2387c138-d607-9c92-9829-9c0adb12b9fd",
"debug_status": "found",
"features": {
"has_debug_info": true,
"has_sources": true,
"has_symbols": true,
"has_unwind_info": true
}
}
TombstoneMerged event has no image with that debug id. Its missing images are system/ART/OAT images, for example:
{
"code_file": "/system/framework/arm64/boot-framework.oat",
"debug_status": "missing"
}
Minimal reproduction
Flutter init:
await SentryFlutter.init(
(options) {
options.dsn = '<dsn>';
options.release = 'sentry_demo@1.0.0+1';
options.dist = '1';
options.enableTombstone = true;
options.attachThreads = true;
},
appRunner: () => runApp(const App()),
);
Dart trigger:
static const _nativeChannel = MethodChannel('sentry_demo/native');
Future<void> triggerNativeCrash() async {
await _nativeChannel.invokeMethod('triggerRealNativeCrash');
}
Android MainActivity.kt:
class MainActivity : FlutterActivity() {
external fun triggerNativeSegfault()
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "sentry_demo/native")
.setMethodCallHandler { call, result ->
if (call.method == "triggerRealNativeCrash") {
triggerNativeSegfault()
} else {
result.notImplemented()
}
}
}
companion object {
init {
System.loadLibrary("sentry_demo_native")
}
}
}
Native crash source:
#include <jni.h>
extern "C" JNIEXPORT void JNICALL
Java_com_example_sentry_1demo_MainActivity_triggerNativeSegfault(JNIEnv *, jobject) {
volatile int *crash_address = nullptr;
*crash_address = 1;
}
Release build setup:
- Flutter app using
sentry_flutter: ^9.22.0
- Android release build with R8 enabled
- Native debug symbols uploaded to Sentry
- Android 12 device
- Native SIGSEGV triggered from JNI/C++
Why this looks related to the tombstone merge path
From PR #5037, the merge strategy appears to replace debugMeta, exception, and threads with data from the tombstone parser. In this case, the original native SDK event had a found app debug image, but the TombstoneMerged event does not. It looks like the merge/parsing path drops or fails to reconstruct the app native image required for symbolication.
Additional note
The ProGuard UUID is present in the tombstone merged event, but Java/OAT frames such as P.a.onMethodCall also remain obfuscated in the stack. The main blocker here is that the app native frame no longer resolves to source file/line after the event becomes TombstoneMerged.
Description
When
enableTombstoneis enabled in a Flutter Android app, a native SIGSEGV crash is reported as aTombstoneMergedevent. Compared with the regular nativesignalhandlerevent for the same crash, the merged tombstone event no longer contains the app native library debug image indebugmeta.images, so Sentry cannot symbolicate the app frame to the source file and line.The regular native crash resolves to
native_crash.cpp, but theTombstoneMergedevent only shows the JNI symbol/address.Expected behavior
The merged tombstone event should preserve enough native debug image information from the original native SDK event, or include the app native library image parsed from the tombstone, so the app frame can still be symbolicated to source file and line.
Actual behavior
Regular native crash event (
mechanism=signalhandler) is symbolicated:a0fc8e59e5a84631746cfb62af3cf072sentry.native.android.flutter 0.14.22387c138-d607-9c92-9829-9c0adb12b9fdfoundhas_debug_info=true,has_sources=true,has_symbols=true,has_unwind_info=trueJava_com_example_sentry_1demo_MainActivity_triggerNativeSegfaultnative_crash.cppandroid/app/src/main/cpp/native_crash.cppTombstone merged event is not symbolicated to source file/line:
ba490da4525e4ec519f0fbf27c1966besentry.native.android.flutter 0.15.2TombstoneMergedbase.apk!libsentry_demo_native.so 0x79e0279618 Java_com_example_sentry_1demo_MainActivity_triggerNativeSegfault2387c138-d607-9c92-9829-9c0adb12b9fdindebugmeta.images.boot.oat,boot-framework.oat,libc.so,libandroid_runtime.so.Relevant debugmeta comparison
Regular
signalhandlerevent includes the app native image and Sentry finds uploaded symbols:{ "type": "elf", "code_file": "/data/app/.../base.apk", "debug_id": "2387c138-d607-9c92-9829-9c0adb12b9fd", "debug_status": "found", "features": { "has_debug_info": true, "has_sources": true, "has_symbols": true, "has_unwind_info": true } }TombstoneMergedevent has no image with that debug id. Its missing images are system/ART/OAT images, for example:{ "code_file": "/system/framework/arm64/boot-framework.oat", "debug_status": "missing" }Minimal reproduction
Flutter init:
Dart trigger:
Android
MainActivity.kt:Native crash source:
Release build setup:
sentry_flutter: ^9.22.0Why this looks related to the tombstone merge path
From PR #5037, the merge strategy appears to replace
debugMeta,exception, andthreadswith data from the tombstone parser. In this case, the original native SDK event had a found app debug image, but theTombstoneMergedevent does not. It looks like the merge/parsing path drops or fails to reconstruct the app native image required for symbolication.Additional note
The ProGuard UUID is present in the tombstone merged event, but Java/OAT frames such as
P.a.onMethodCallalso remain obfuscated in the stack. The main blocker here is that the app native frame no longer resolves to source file/line after the event becomesTombstoneMerged.