-
Notifications
You must be signed in to change notification settings - Fork 655
Description
Summary
Our Flutter application experiences a fatal crash inside Crashlytics itself.
Crashlytics fails to serialize the crash event due to an OutOfMemoryError in the JSON encoder.
Because serialization fails:
- Crashlytics never uploads such a crash due to which this crash is arise
- The original crash cause is lost
- The app experiences a second fatal crash caused by Crashlytics
- Flutter cannot intercept or trim logs because no callbacks exist for fatal crashes
This makes the issue impossible to work around from the application side.
Stacktrace
Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 9232 byte allocation with 537312 free bytes and 524KB until OOM, target footprint 268435456, growth limit 268435456; giving up on allocation because <1% of heap free after GC. at java.util.Arrays.copyOf(Arrays.java:3785) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:182) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:758) at java.lang.StringBuffer.append(StringBuffer.java:431) at java.io.StringWriter.write(StringWriter.java:77) at android.util.JsonWriter.string(JsonWriter.java:453) at android.util.JsonWriter.value(JsonWriter.java:305) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.add(JsonValueObjectEncoderContext.java:170) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.add(JsonValueObjectEncoderContext.java:33) at com.google.firebase.encoders.json.JsonDataEncoderBuilder.lambda$static$1(JsonDataEncoderBuilder.java:63) at com.google.firebase.encoders.json.JsonDataEncoderBuilder$$ExternalSyntheticLambda1.encode(D8$$SyntheticClass) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.add(JsonValueObjectEncoderContext.java:314) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.internalAddIgnoreNullValues(JsonValueObjectEncoderContext.java:384) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.add(JsonValueObjectEncoderContext.java:69) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.add(JsonValueObjectEncoderContext.java:110) at com.google.firebase.crashlytics.internal.model.AutoCrashlyticsReportEncoder$CrashlyticsReportSessionEventLogEncoder.encode(AutoCrashlyticsReportEncoder.java:588) at com.google.firebase.crashlytics.internal.model.AutoCrashlyticsReportEncoder$CrashlyticsReportSessionEventLogEncoder.encode(AutoCrashlyticsReportEncoder.java:580) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.doEncode(JsonValueObjectEncoderContext.java:334) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.add(JsonValueObjectEncoderContext.java:309) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.internalAddIgnoreNullValues(JsonValueObjectEncoderContext.java:384) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.add(JsonValueObjectEncoderContext.java:69) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.add(JsonValueObjectEncoderContext.java:110) at com.google.firebase.crashlytics.internal.model.AutoCrashlyticsReportEncoder$CrashlyticsReportSessionEventEncoder.encode(AutoCrashlyticsReportEncoder.java:299) at com.google.firebase.crashlytics.internal.model.AutoCrashlyticsReportEncoder$CrashlyticsReportSessionEventEncoder.encode(AutoCrashlyticsReportEncoder.java:277) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.doEncode(JsonValueObjectEncoderContext.java:334) at com.google.firebase.encoders.json.JsonValueObjectEncoderContext.add(JsonValueObjectEncoderContext.java:309) at com.google.firebase.encoders.json.JsonDataEncoderBuilder$1.encode(JsonDataEncoderBuilder.java:121) at com.google.firebase.encoders.json.JsonDataEncoderBuilder$1.encode(JsonDataEncoderBuilder.java:129) at com.google.firebase.crashlytics.internal.model.serialization.CrashlyticsReportJsonTransform.eventToJson(CrashlyticsReportJsonTransform.java:48) at com.google.firebase.crashlytics.internal.persistence.CrashlyticsReportPersistence.persistEvent(CrashlyticsReportPersistence.java:137) at com.google.firebase.crashlytics.internal.common.SessionReportingCoordinator.lambda$persistEvent$0$com-google-firebase-crashlytics-internal-common-SessionReportingCoordinator(SessionReportingCoordinator.java:352) at com.google.firebase.crashlytics.internal.common.SessionReportingCoordinator$$ExternalSyntheticLambda0.run(D8$$SyntheticClass) at com.google.firebase.crashlytics.internal.concurrency.CrashlyticsWorker.lambda$submit$1(CrashlyticsWorker.java:96) at com.google.firebase.crashlytics.internal.concurrency.CrashlyticsWorker$$ExternalSyntheticLambda0.then(D8$$SyntheticClass) at com.google.android.gms.tasks.zze.run(com.google.android.gms:play-services-tasks@@18.1.0:1) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1156) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:651) at com.google.firebase.concurrent.CustomThreadFactory.lambda$newThread$0$com-google-firebase-concurrent-CustomThreadFactory(CustomThreadFactory.java:47) at com.google.firebase.concurrent.CustomThreadFactory$$ExternalSyntheticLambda0.run(D8$$SyntheticClass) at java.lang.Thread.run(Thread.java:1119)
This shows the crash occurs entirely inside Crashlytics while constructing the JSON crash report.
Environment
Flutter Version: (your version used)
Android OS: devices with 2–4GB RAM affected.
App Type: Real-time CCTV app displaying a new image every second (high memory churn).
FlutterFire Libraries
firebase_analytics: 11.4.4
firebase_core: 3.12.1
firebase_crashlytics: 4.3.1
Crashlytics Android SDK version is auto-managed by FlutterFire.
Behavior Observed
- A fatal crash happens in the app.
- Crashlytics attempts to persist the crash event.
- The JSON encoder (JsonWriter) allocates a very large StringWriter buffer.
- The allocation fails → OutOfMemoryError.
- Crashlytics itself crashes the app again.
- Crash is never uploaded to Firebase.
- didCrashOnPreviousExecution() remains false because persistence never finished.
- Flutter receives no callback, no event, no logs.
This makes it impossible for us to detect, trim, or reduce the crash report.
Why This is a Crashlytics Library Issue
- Crash is happening inside Crashlytics persistence layer
- Developers have no API to intercept, trim, or limit event size
- Crashlytics does not cap JSON event serialization memory
- Crashlytics should never crash the app while trying to log a crash
Targeted Platforms
- Android