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 11.7.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.
If you're using Unity IL2CPP and you're seeing unsymbolicated stack traces, then try the following:
Make sure that you're using v8.6.1 or higher of the Crashlytics Unity SDK.
Make sure that you're set up for and running the Firebase CLI
crashlytics:symbols:upload
command to generate and upload your symbol file.You need to run this CLI command each time that you create a release build or any build for which you want to see symbolicated stack traces in the Firebase console. Learn more in the Get readable crash reports page.
Yes, Crashlytics can display symbolicated stack traces for your apps that use IL2CPP. This capability is available for apps released on either Android or Apple platforms. Here's what you need to do:
Make sure that you're using v8.6.0 or higher of the Crashlytics Unity SDK.
Complete the necessary tasks for your platform:
For Apple platform apps: No special actions are needed. For Apple platform apps, the Firebase Unity Editor plugin automatically configures your Xcode project to upload symbols.
For Android apps: Make sure that you're set up for and running the Firebase CLI
crashlytics:symbols:upload
command to generate and upload your symbol file.You need to run this CLI command each time that you create a release build or any build for which you want to see symbolicated stack traces in the Firebase console. Learn more in the Get readable crash reports page.
The crash-free value represents the percentage of users who engaged with your app but did not have a crash over a specific time period.
Here is the formula for calculating the crash-free users percentage. Its input values are provided by Google Analytics.
CRASH_FREE_USERS_PERCENTAGE = 1 - (CRASHED_USERS / ALL_USERS) x 100
When a crash happens, Google Analytics sends an
app_exception
event type, and CRASHED_USERS represents the number of users associated with that event type.ALL_USERS represents the total number of users who engaged with your app over the time period that you've selected from the drop-down menu in the upper-right of the Crashlytics dashboard.
The crash-free users percentage is an aggregation over time, not an average.
For example, imagine your app has three users; we'll call them User A, User B, and User C. The following table shows which users engaged with your app each day and which of those users had a crash that day:
Monday | Tuesday | Wednesday | |
---|---|---|---|
Users who engaged with your app | A, B, C | A, B, C | A, B |
User that had a crash | C | B | A |
On Wednesday, your crash-free users percentage is 50% (1 out of 2 users was crash-free).
Two of your users engaged with your app on Wednesday, but only one of them (User B) had no crashes.For the past 2 days, your crash-free users percentage is 33.3% (1 out of 3 users was crash-free).
Three of your users engaged with your app over the past two days, but only one of them (User C) had no crashes.For the past 3 days, your crash-free users percentage is 0% (0 out of 3 users were crash-free).
Three of your users engaged with your app over the past three days, but zero of them had no crashes.
The crash-free users value shouldn't be compared over different time periods. The probability of a single user experiencing a crash grows the more times they use your app, so the crash-free users value is likely to be smaller for longer time periods.
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.
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.
Reporting uncaught exceptions as fatals
Crashlytics can report uncaught exceptions as fatals (starting with v10.4.0 of the Unity SDK). The following FAQs help to explain the rationale and best practices for using this feature.
By reporting uncaught exceptions as fatals, you get a more realistic indication of what exceptions may result in the game being unplayable – even if the app continues to run.
Note that if you start reporting fatals, your crash-free users (CFU) percentage will likely decrease, but the CFU metric will be more representative of the end-users' experiences with your app.
In order for Crashlytics to report an uncaught exception as fatal, both of the following two conditions must be met:
During initialization in your app, the
ReportUncaughtExceptionsAsFatal
property must be set totrue
.Your app (or an included library) throws an exception that isn't caught. An exception that's created, but not thrown, is not considered uncaught.
When you start getting reports of your uncaught exceptions as fatals, here are some options for handling these uncaught exceptions:
- Consider how you can start catching and handling these uncaught exceptions.
- Consider different options for logging exceptions to the Unity debug console and to Crashlytics.
Catch and handle thrown exceptions
Exceptions are created and thrown to reflect unexpected or exceptional states. Resolving the issues reflected by a thrown exception involves returning the program to a known state (a process known as exception handling).
It's best practice to catch and handle all foreseen exceptions unless the program cannot be returned to a known state.
To control which sorts of exceptions are caught and handled by what code,
wrap code that might generate an exception in a try-catch
block.
Make sure that the conditions in the catch
statements are as narrow as
possible to handle the specific exceptions appropriately.
Log exceptions in Unity or Crashlytics
There are multiple ways to record exceptions in Unity or Crashlytics to help debug the issue.
When using Crashlytics, here are the two most common and recommended options:
Option 1: Print in the Unity console, but don't report to Crashlytics, during development or troubleshooting
- Print to the Unity console using
Debug.Log(exception)
,Debug.LogWarning(exception)
, andDebug.LogError(exception)
which print the contents of the exception to the Unity console and don't re-throw the exception.
- Print to the Unity console using
Option 2: Upload to Crashlytics for consolidated reporting in the Crashlytics dashboard for the following situations:
- If an exception is worth logging to debug a possible subsequent
Crashlytics event, then use
Crashlytics.Log(exception.ToString())
. - If an exception should still be reported to Crashlytics despite
being caught and handled, then use
Crashlytics.LogException(exception)
to log it as a nonfatal event.
- If an exception is worth logging to debug a possible subsequent
Crashlytics event, then use
However, if you want to manually report a fatal event to Unity Cloud
Diagnostics, you can use Debug.LogException
. This option prints the exception
to the Unity console like Option 1, but it also throws the exception
(whether or not it has been thrown or caught yet). It throws the error
nonlocally. This means that even a surrounding Debug.LogException(exception)
with try-catch
blocks still results in an uncaught exception.
Therefore, call Debug.LogException
if and only if you want to do all of
the following:
- To print the exception to the Unity console.
- To upload the exception to Crashlytics as a fatal event.
- To throw the exception, have it be treated as an uncaught exception, and have it be reported to Unity Cloud Diagnostics.
Note that if you want to print a caught exception to the Unity console and upload to Crashlytics as a nonfatal event, do the following instead:
try
{
methodThatThrowsMyCustomExceptionType();
}
catch(MyCustomExceptionType exception)
{
// Print the exception to the Unity console at the error level.
Debug.LogError(exception);
// Upload the exception to Crashlytics as a non-fatal event.
Crashlytics.LogException(exception); // not Debug.LogException
//
// Code that handles the exception
//
}