This page provides troubleshooting help and answers to frequently-asked questions about using Crashlytics. If you can't find what you're looking for or need additional help, contact Firebase support.
General troubleshooting/FAQ
You might notice two different formats for issues listed in your Issues table in the Firebase console. And you might also notice a feature called "variants" within some of your issues. Here's why!
In early 2023, we rolled out an improved analysis engine for grouping events as well as an updated design and some advanced features for new issues (like variants!). Check out our recent blog post for all the details, but you can read below for the highlights.
Crashlytics analyzes all the events from your app (like crashes, non-fatals, and ANRs) and creates groups of events called issues — all events in an issue have a common point of failure.
To group events into these issues, the improved analysis engine now looks at many aspects of the event, including the frames in the stack trace, the exception message, the error code, and other platform or error type characteristics.
However, within this group of events, the stack traces leading to the failure might be different. A different stack trace could mean a different root cause. To represent this possible difference within an issue, we now create variants within issues - each variant is a sub-group of events in an issue that have the same failure point and a similar stack trace. With variants, you can debug the most common stack traces within an issue and determine if different root causes are leading to the failure.
Here's what you'll experience with these improvements:
Revamped metadata displayed within the issue row
It's now easier to understand and triage issues in your app.Fewer duplicate issues
A line number change doesn't result in a new issue.Easier debugging of complex issues with various root causes
Use variants to debug the most common stack traces within an issue.More meaningful alerts and signals
A new issue actually represents a new bug.More powerful search
Each issue contains more searchable metadata, like exception type and package name.
Here's how these improvements are rolling out:
When we get new events from your app, we'll check if they match to an existing issue.
If there's no match, we'll automatically apply our smarter event-grouping algorithm to the event and create a new issue with the revamped metadata design.
This is the first big update that we're making to our event grouping. If you have feedback or encounter any issues, please let us know by filing a report.
If you're not seeing crash-free metrics (like crash-free users and sessions) and/or velocity alerts, make sure that you're using the Crashlytics SDK v18.6.0+ (or Firebase BoM v32.6.0+).
If you're not seeing breadcrumb logs, we recommend checking your app's configuration for Google Analytics. Make sure you meet the following requirements:
You've enabled Google Analytics in your Firebase project.
You've enabled Data sharing for Google Analytics. Learn more about this setting in Manage your Analytics data sharing settings
You've added the Firebase SDK for Google Analytics to your app. This SDK must be added in addition to the Crashlytics SDK.
You're using the latest Firebase SDK versions for all the products that you use in your app.
Especially check that you're using at minimum the following version of the Firebase SDK for Google Analytics:
Android — v17.2.3+ (BoM v24.7.1+) .
Crashlytics supports ANR reporting for Android apps from devices that run Android 11 and higher. The underlying API that we use to collect ANRs (getHistoricalProcessExitReasons) is more reliable than SIGQUIT or watchdog-based approaches. This API is available only on Android 11+ devices.
If some of your ANRs are missing their BuildId
s, troubleshoot as follows:
Make sure that you're using an up-to-date Crashlytics Android SDK and Crashlytics Gradle plugin version.
If you're missing
BuildId
s for Android 11 and some Android 12 ANRs, then it's likely that you're using an out-of-date SDK, Gradle plugin, or both. To properly collectBuildId
s for these ANRs, you need to use the following versions:- Crashlytics Android SDK v18.3.5+ (Firebase BoM v31.2.2+)
- Crashlytics Gradle plugin v2.9.4+
Check if you're using a non-standard location for your shared libraries.
If you're only missing
BuildId
s for your app’s shared libraries, it's likely that you're not using the standard, default location for shared libraries. If this is the case, then Crashlytics might not be able to locate the associatedBuildId
s. We recommend that you consider using the standard location for shared libraries.Make sure that you're not stripping
BuildId
s during the build process.Note that the following troubleshooting tips apply to both ANRs and native crashes.
Check if the
BuildId
s exist by runningreadelf -n
on your binaries. If theBuildId
s are absent, then add-Wl,--build-id
to the flags for your build system.Check that you're not unintentionally stripping the
BuildId
s in an effort to reduce your APK size.If you keep stripped and unstripped versions of a library, make sure to point to the correct version in your code.
There can be a mismatch between the count of ANRs between Google Play and Crashlytics. This is expected due to the difference in the mechanism of collecting and reporting ANR data. Crashlytics reports ANRs when the app next starts up, whereas Android Vitals sends ANR data after the ANR occurs.
Additionally, Crashlytics only displays ANRs that occur on devices running Android 11+, compared to Google Play which displays ANRs from devices with Google Play services and data collection consent accepted.
LLVM and GNU toolchains have distinct defaults and treatments for the read-only segment of your app's binaries, which may generate inconsistent stack traces in the Firebase console. To mitigate this, add the following linker flags to your build process:
If you're using the
lld
linker from the LLVM toolchain, add:-Wl,--no-rosegment
If you're using the
ld.gold
linker from the GNU toolchain, add:-Wl,--rosegment
If you're still seeing stack trace inconsistencies (or if neither flag is pertinent to your toolchain), try adding the following to your build process instead:
-fno-omit-frame-pointer
The Crashlytics plugin bundles a
customized Breakpad symbol file generator.
If you prefer to use your own binary for generating Breakpad symbol files (for
example, if you prefer to build all native executables in your build chain from
source), use the optional symbolGeneratorBinary
extension property to specify
the path to the executable.
You can specify the path to the Breakpad symbol file generator binary in one of two ways:
Option 1: Specify the path via the
firebaseCrashlytics
extension in yourbuild.gradle
fileAdd the following to your app-level
build.gradle.kts
file:Gradle plugin v3.0.0+
android { buildTypes { release { configure<CrashlyticsExtension> { nativeSymbolUploadEnabled = true // Add these optional fields to specify the path to the executable symbolGeneratorType = "breakpad" breakpadBinary = file("/PATH/TO/BREAKPAD/DUMP_SYMS") } } } }
lower plugin versions
android { // ... buildTypes { // ... release { // ... firebaseCrashlytics { // existing; required for either symbol file generator nativeSymbolUploadEnabled true // Add this optional new block to specify the path to the executable symbolGenerator { breakpad { binary file("/PATH/TO/BREAKPAD/DUMP_SYMS") } } } } }
Option 2: Specify the path via a property line in your Gradle properties file
You can use the
com.google.firebase.crashlytics.breakpadBinary
property to specify the path to the executable.You can manually update your Gradle properties file or update the file via the command line. For example, to specify the path via the command line, use a command like the following:
./gradlew -Pcom.google.firebase.crashlytics.symbolGenerator=breakpad \ -Pcom.google.firebase.crashlytics.breakpadBinary=/PATH/TO/BREAKPAD/DUMP_SYMS \ app:assembleRelease app:uploadCrashlyticsSymbolFileRelease
If you see the following exception, it's likely you're using a version of DexGuard that's incompatible with the Firebase Crashlytics SDK:
java.lang.IllegalArgumentException: Transport backend 'cct' is not registered
This exception does not crash your app but prevents it from sending crash reports. To fix this:
Make sure you're using the latest DexGuard 8.x release. The latest version contains rules that are required by the Firebase Crashlytics SDK.
If you don't want to change your DexGuard version, try adding the following line to your obfuscation rules (in your DexGuard config file):
-keepresourcexmlelements manifest/application/service/meta-data@value=cct
When an app uses an obfuscator that doesn't expose the file extension,
Crashlytics generates each issue with a .java
file extension by default.
So that Crashlytics can generate issues with the correct file extension, make sure your app uses the following setup:
- Uses Android Gradle 4.2.0 or higher
- Uses R8 with obfuscation turned on. To update your app to R8, follow this documentation.
Note that after updating to the setup described above, you might start seeing
new .kt
issues that are duplicates of existing .java
issues. See the
FAQ to learn more about that circumstance.
Starting in mid-December 2021, Crashlytics improved support for applications that use Kotlin.
Until recently, the available obfuscators did not expose the file extension, so
Crashlytics generated each issue with a .java
file extension by default.
However, as of Android Gradle 4.2.0, R8 supports file extensions.
With this update, Crashlytics can now determine if each class used within
the app is written in Kotlin and include the correct filename in the issue
signature. Crashes are now correctly attributed to .kt
files (as appropriate)
if your app has the following setup:
- Your app uses Android Gradle 4.2.0 or higher.
- Your app uses R8 with obfuscation turned on.
Since new crashes now include the correct file extension in their issue
signatures, you might see new .kt
issues that are actually just duplicates of
existing .java
-labeled issues. In the Firebase console, we try to identify
and communicate to you if a new .kt
issue is a possible duplicate of an
existing .java
-labeled issue.
Notes allow project members to comment on specific issues with questions, status updates, etc.
When a project member posts a note, it's labeled with the email of their Google account. This email address is visible, along with the note, to all project members with access to view the note.
The following describes the access required to view, write, and delete notes:
Project members with any of the following roles can view and delete existing notes and write new notes on an issue.
- Project Owner or Editor, Firebase Admin, Quality Admin, or Crashlytics Admin
Project members with any of the following roles can view the notes posted on an issue, but they cannot delete or write a note.
- Project Viewer, Firebase Viewer, Quality Viewer, or Crashlytics Viewer
See Understand crash-free metrics.
Notes allow project members to comment on specific issues with questions, status updates, etc.
When a project member posts a note, it's labeled with the email of their Google account. This email address is visible, along with the note, to all project members with access to view the note.
The following describes the access required to view, write, and delete notes:
Project members with any of the following roles can view and delete existing notes and write new notes on an issue.
- Project Owner or Editor, Firebase Admin, Quality Admin, or Crashlytics Admin
Project members with any of the following roles can view the notes posted on an issue, but they cannot delete or write a note.
- Project Viewer, Firebase Viewer, Quality Viewer, or Crashlytics Viewer
Integrations
If your project uses Crashlytics alongside the Google Mobile Ads SDK,
it's likely that the crash reporters are interfering when
registering exception handlers. To fix the issue, turn off crash reporting in
the Mobile Ads SDK by calling disableSDKCrashReporting
.
After you link Crashlytics to BigQuery, new datasets you create are automatically located in the United States, regardless of the location of your Firebase project.
Platform support
The Firebase Crashlytics NDK does not support ARMv5 (armeabi). Support for this ABI was removed as of NDK r17.
Regressed issues
An issue has had a regression when you've previously closed the issue but Crashlytics gets a new report that the issue has re-occurred. Crashlytics automatically re-opens these regressed issues so that you can address them as appropriate for your app.
Here's an example scenario that explains how Crashlytics categorizes an issue as a regression:
- For the first time ever, Crashlytics gets a crash report about Crash "A". Crashlytics opens a corresponding issue for that crash (Issue "A").
- You fix this bug quickly, close Issue "A", and then release a new version of your app.
- Crashlytics gets another report about Issue "A" after you've closed the
issue.
- If the report is from an app version that Crashlytics knew about when you closed the issue (meaning that the version had sent a crash report for any crash at all), then Crashlytics won't consider the issue as regressed. The issue will remain closed.
- If the report is from an app version that Crashlytics did not know about when you closed the issue (meaning that the version had never sent any crash report for any crash at all), then Crashlytics considers the issue regressed and will re-open the issue.
When an issue regresses, we send a regression detection alert and add a regression signal to the issue to let you know that Crashlytics has re-opened the issue. If you do not want an issue to re-open due to our regression algorithm, "mute" the issue instead of closing it.
If a report is from an old app version that had never sent any crash reports at all when you closed the issue, then Crashlytics considers the issue regressed and will re-open the issue.
This situation can happen in the following situation: You've fixed a bug and released a new version of your app, but you still have users on older versions without the bug fix. If, by chance, one of those older versions had never sent any crash reports at all when you closed the issue, and those users start encountering the bug, then those crash reports would trigger a regressed issue.
If you do not want an issue to re-open due to our regression algorithm, "mute" the issue instead of closing it.