A new feature has been released on The Perfect App (TPA) which makes it possible to report Non-Fatal issues in your app. In the following I will explain the difference between Fatal and Non-Fatal issues, and why Non-Fatal issues can be just as big a problem as Fatal issues. I will also explain how to use the feature in order to get the most out of it.
A Non-Fatal Issue Can be as Fatal as a Crash
Fatal issues, also known as crashes, happen (mostly) when you as a developer make some kind of programming mistake (no offense, but it is extremely rarely the compiler 😊). The user taps a button and the app disappears. This is a frustrating situation to the user which may have lost all or part of his/her work or game progress etc. Fatal issues are easily detected and all information available is gathered from the system and send automatically to TPA when the app is restarted.
Non-Fatal issues do not make the app crash. A Non-Fatal issue is when the app reaches an invalid state which should not happen. When the app is in an invalid state, the developers expectations will no longer be correct and this can severely affect the user experience.
- The app may be locked making it necessary to force quit it
- Wrong data may be presented to the user
- User data may become corrupted
- The app may react incorrectly
All kinds of scenarios, which can make the user believe it is a broken app, that cannot be counted on. Unfortunately these scenarios cannot be detected automatically, since only the developer knows what should actually happen. The developer does, however, in some cases know that certain code paths shall never be reached, such as some exceptions or default values in a switch-statement.
In these cases, the developer can report a Non-Fatal issue to TPA, which will send a stack trace (similar to Fatal issues), and any additional information that is provided. Since the developer decides when to report the issue, additional information can often be provided, which will help understand what happened and why.
Non-Fatal issues will be shown in line with Fatal issues and you will be notified on Mail, Slack and JIRA as configured.
With Great Power Comes Great Responsibility
Reporting Non-Fatal issues is a powerful tool to find and fix issues in your apps. It is important to consider when to report an issue and when it does not make sense. Reporting too many (non-relevant) issues will clutter your mail box and your list of issues on TPA, making it hard to find the issues that you can actually fix.
Do not report issues, that will happen due to external circumstances, that you will not be able to fix:
- Networking errors
- Low memory warnings
- Incorrect input from user
In general, you shall be able to fix the reported error and mark it as resolved in TPA. If you cannot fix it, you will always have issues shown in TPA. If you want to know how often networking errors occur, track it as a user event instead. Implementing reporting of Non-Fatal issues will however be an iterative process. Reporting an issue at an invalid code path may reveal that additional error handling needs to be implemented. Furthermore, reporting Non-Fatal issues about backend output, may reveal that data that was not expected needs to be handled in the app.
Reporting Non-Fatal Issues to TPA
Reporting a Non-Fatal issue is simple. First make sure that you are running the latest version of the TPA SDKs:
- Android: 1.7.0
- iOS: 4.7.0
The following will show iOS examples, but similar methods are available for Android.
In its simplest version, you can call:
This will send a stack trace to TPA and Non-Fatal incidents with similar stack traces will be grouped together as the same issue. It is also possible to add a reason when reporting the issue, to provide relevant info about why it happened. When providing a reason, incidents with the same reason will be grouped as the same issue instead of using the stack trace to group the incidents. In the following example, all incidents reported with the reason “Invalid state reported from backend” will be grouped as a single issue no matter where in the source code they are reported from:
TPAManager.shared().reportNonFatalIssue(withReason: "Invalid state reported from backend")
It may even make sense to include the state since we do not expect an infinite amount of different states from the backend:
TPAManager.shared().reportNonFatalIssue(withReason: "Invalid state reported from backend: \(state)")
Two different invalid states will result in two different issue groups on TPA. When a fix is made to handle a new state, that issue can be marked as closed on TPA. Be aware, that including variable parameters may have a very bad effect on the issue grouping. In the following example, a new issue group will be created every time a new number of bytes was received from the backend.
// Do not do this TPAManager.shared().reportNonFatalIssue(withReason: "Too many bytes received from backend: \(numberOfBytes)")
Most likely a lot of issue groups will be created on TPA with only a few incidents in each group, and the fix for all of them, will most likely be the same. The number of bytes may still be relevant when fixing the issue, but instead of including it in the reason, it can be sent as userInfo in an NSError object:
// Add variable data in user dictionary TPAManager.shared().reportNonFatalIssue(withReason: "Too many bytes received from backend", error: NSError(domain: "Backend issue", code: 0, userInfo: ["Number of Bytes": 123]))
The information can be found on each single incident below the Thread State:
Finding Non-Fatal issues have never been easier - get started and help your users to a better app experience.
Let us now if you have any comments or questions on firstname.lastname@example.org.