You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On Android, native crash events (type=crash) always arrive in Grafana with context_stacktrace="No stacktrace", even when ApplicationExitInfo has
captured a trace. The root cause is a JSON key mismatch between the Android
plugin and the Dart side of the SDK, plus a missing forward of the field.
Reproduced on faro: 0.14.0 (latest, published 2026-04-14) against a
Flutter demo app running on an Android 11 emulator (API 30). The app
triggered a Kotlin NullPointerException (via value!!.length) on the
main thread, which is a REASON_CRASH from ApplicationExitInfo.
The Dart side reads from "stacktrace" — a key that never exists:
lib/src/faro.dart (around line 763):
final stacktrace =
stringifiedContext['stacktrace'] ??'No stacktrace'; // <-- wrong key
Result: the fallback literal string 'No stacktrace' is always used.
2. The "trace" field is not forwarded in the error context
Even if the Dart code read the right key, the context passed to pushError is a hard-coded allow-list of six fields and does not
include any trace:
lib/src/faro.dart (around line 773):
_instance.pushError(
type:'crash',
value:'$reason , status: $status',
context: {
'description': description,
'stacktrace': stacktrace, // <-- must also be populated here'timestamp': timestamp,
'timestamp_readable_utc': humanReadableTimestamp,
'importance': importance,
'processName': processName,
},
);
So even after fixing the key, the trace would still be discarded unless
this map is updated.
Expected behavior
When ApplicationExitInfo.getTraceInputStream() returns a non-null,
non-empty trace for REASON_CRASH, REASON_CRASH_NATIVE, or REASON_ANR,
that trace should appear on the resulting Faro event in a usable form
(either as a parsed set of StackFrames — per #212 — or at minimum as
a context_stacktrace text field).
Scope
Affected: All Android native crashes reported through enableCrashReporter() (JVM crashes, native NDK crashes via REASON_CRASH_NATIVE). This is the entire native-crash path on Android.
Not affected: iOS crashes (separate codepath via CrashReportingIntegration.swift / PLCrashReporter) and Dart unhandled
exceptions (via FlutterError.onError / zone handler).
final stacktrace =
stringifiedContext['trace'] ??'No stacktrace'; // read "trace"
and make sure it ends up in the forwarded context (the map already has a 'stacktrace' key, so the fix is purely the read key).
A follow-up, aligned with #212, would be to parse the Java-format trace
into structured StackFrames so it renders like a Dart exception in
Grafana Frontend Observability.
Caveat about Android itself
Independent of these SDK bugs: ApplicationExitInfo.getTraceInputStream()
is only documented to reliably return a trace for REASON_ANR and REASON_CRASH_NATIVE. For REASON_CRASH (JVM exceptions) it is often
null on many OEMs / Android versions. So even with the SDK fixed,
JVM-crash traces may still be missing on some devices. This is an
Android limitation, not an SDK bug — but it's worth documenting.
Description
On Android, native crash events (
type=crash) always arrive in Grafana withcontext_stacktrace="No stacktrace", even whenApplicationExitInfohascaptured a trace. The root cause is a JSON key mismatch between the Android
plugin and the Dart side of the SDK, plus a missing forward of the field.
Reproduced on
faro: 0.14.0(latest, published 2026-04-14) against aFlutter demo app running on an Android 11 emulator (API 30). The app
triggered a Kotlin
NullPointerException(viavalue!!.length) on themain thread, which is a
REASON_CRASHfromApplicationExitInfo.Example event in Loki (trimmed):
Note the literal string
"No stacktrace"— it is a hard-coded Dartfallback, not a missing field.
Root cause
There are two compounding issues in the SDK. Either alone would be
enough to produce the symptom.
1. Key mismatch between Android and Dart
The Android plugin writes the trace under the key
"trace":android/src/main/java/com/grafana/faro/ExitInfoHelper.java(around line 159):The Dart side reads from
"stacktrace"— a key that never exists:lib/src/faro.dart(around line 763):Result: the fallback literal string
'No stacktrace'is always used.2. The
"trace"field is not forwarded in the error contextEven if the Dart code read the right key, the context passed to
pushErroris a hard-coded allow-list of six fields and does notinclude any trace:
lib/src/faro.dart(around line 773):So even after fixing the key, the trace would still be discarded unless
this map is updated.
Expected behavior
When
ApplicationExitInfo.getTraceInputStream()returns a non-null,non-empty trace for
REASON_CRASH,REASON_CRASH_NATIVE, orREASON_ANR,that trace should appear on the resulting Faro event in a usable form
(either as a parsed set of
StackFrames— per #212 — or at minimum asa
context_stacktracetext field).Scope
enableCrashReporter()(JVM crashes, native NDK crashes viaREASON_CRASH_NATIVE). This is the entire native-crash path on Android.CrashReportingIntegration.swift/ PLCrashReporter) and Dart unhandledexceptions (via
FlutterError.onError/ zone handler).text rather than structured frames. That's a separate codepath
(
native_integration.dart→_getAnrStatus()), not thegetCrashReport()path discussed here.Suggested fix
Minimal change in
lib/src/faro.dart:and make sure it ends up in the forwarded context (the map already has a
'stacktrace'key, so the fix is purely the read key).A follow-up, aligned with #212, would be to parse the Java-format trace
into structured
StackFramesso it renders like a Dart exception inGrafana Frontend Observability.
Caveat about Android itself
Independent of these SDK bugs:
ApplicationExitInfo.getTraceInputStream()is only documented to reliably return a trace for
REASON_ANRandREASON_CRASH_NATIVE. ForREASON_CRASH(JVM exceptions) it is oftennull on many OEMs / Android versions. So even with the SDK fixed,
JVM-crash traces may still be missing on some devices. This is an
Android limitation, not an SDK bug — but it's worth documenting.
Environment
faro: 0.14.0sdk_gphone_arm64)Related
(related but distinct codepath; that one gets text through, this one
drops it entirely)