2017-07-28 20:00:39 +00:00
|
|
|
# Error Reporting
|
|
|
|
|
|
|
|
First we need to make the distinction between expected runtime _errors_ and
|
|
|
|
_exceptions_. Unfortunately both are represented with the `Error` class, but
|
|
|
|
they're conceptually different. Exceptions are fatal, errors are not.
|
|
|
|
|
|
|
|
The story around exceptions is simpler so let's start there.
|
|
|
|
|
|
|
|
## Exceptions
|
|
|
|
|
|
|
|
An exception is an unexpected, fatal problem in the app itself. For example, our
|
|
|
|
old friend `undefined is not a function`. This is a problem with the code itself
|
|
|
|
which cannot be resolved at runtime. Our only option is to quit the app and
|
|
|
|
relaunch.
|
|
|
|
|
2017-12-12 11:19:11 +00:00
|
|
|
We handle uncaught exceptions by registering a
|
2017-12-12 23:19:00 +00:00
|
|
|
[global listener](https://github.com/desktop/desktop/blob/fb4e7356/app/src/ui/index.tsx#L75).
|
2017-07-28 20:00:39 +00:00
|
|
|
We report the exception to Central, tell the user that an unrecoverable error
|
|
|
|
happened, and then quit and relaunch. End of story.
|
|
|
|
|
|
|
|
## Errors
|
|
|
|
|
|
|
|
Errors are a bit more involved. They are anything that can go wrong in the
|
|
|
|
standard usage of the app. For example, if the internet's down or a git
|
|
|
|
repository is in a funny state, we're gonna get some errors.
|
|
|
|
|
|
|
|
Our error reporting flows through the `Dispatcher` like most everything in the
|
2017-12-12 11:19:11 +00:00
|
|
|
app.
|
2017-12-12 23:19:00 +00:00
|
|
|
[`postError`](https://github.com/desktop/desktop/blob/fb4e7356/app/src/lib/dispatcher/dispatcher.ts#L308)
|
2017-12-12 11:19:11 +00:00
|
|
|
calls the
|
2017-12-12 23:19:00 +00:00
|
|
|
[registered](https://github.com/desktop/desktop/blob/fb4e7356/app/src/lib/dispatcher/dispatcher.ts#L711)
|
|
|
|
[error handlers](https://github.com/desktop/desktop/blob/fb4e7356/app/src/lib/dispatcher/error-handlers.ts),
|
2017-07-28 20:00:39 +00:00
|
|
|
starting with the most recently registered. The error handlers have the chance
|
2017-08-01 18:51:31 +00:00
|
|
|
to pass the error through untouched, return a different or more specific error,
|
|
|
|
or swallow the error entirely.
|
|
|
|
|
|
|
|
Error handlers must have the following type:
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
export async function myCoolErrorHandler(
|
|
|
|
error: Error,
|
|
|
|
dispatcher: Dispatcher
|
|
|
|
): Promise<Error | null> {
|
|
|
|
// code goes here
|
|
|
|
}
|
|
|
|
```
|
2017-07-28 20:00:39 +00:00
|
|
|
|
|
|
|
If an error passes through all the registered error handlers, the final error
|
2017-12-12 11:19:11 +00:00
|
|
|
handler will call
|
2017-12-12 23:19:00 +00:00
|
|
|
[`Dispatcher#presentError`](https://github.com/desktop/desktop/blob/75445ea6/app/src/lib/dispatcher/dispatcher.ts#L334).
|
2017-07-28 20:00:39 +00:00
|
|
|
That will present the generic error dialog to the user.
|
|
|
|
|
2017-07-28 20:03:13 +00:00
|
|
|
```
|
2017-07-28 20:00:39 +00:00
|
|
|
+------------------------+
|
|
|
|
| |
|
|
|
|
| Dispatcher#postError |
|
|
|
|
| |
|
|
|
|
+------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+------------------+ +--------------------+
|
|
|
|
| | | |
|
|
|
|
| error handlers |-----| do something else |
|
|
|
|
| | | |
|
|
|
|
+------------------+ +--------------------+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+-------------------------+
|
|
|
|
| |
|
|
|
|
| Dispatcher#presentError |
|
|
|
|
| |
|
|
|
|
+-------------------------+
|
2017-07-28 20:03:13 +00:00
|
|
|
```
|
2017-07-28 20:00:39 +00:00
|
|
|
|
|
|
|
### Subclasses
|
|
|
|
|
|
|
|
We have a couple `Error` subclasses which we use to provide more context to
|
|
|
|
error handlers:
|
|
|
|
|
2017-12-12 23:19:00 +00:00
|
|
|
* [`GitError`](https://github.com/desktop/desktop/blob/75445ea6/app/src/lib/git/core.ts#L62) -
|
2017-12-12 11:19:11 +00:00
|
|
|
All errors coming from git should be `GitError`s.
|
2017-12-12 23:19:00 +00:00
|
|
|
* [`ErrorWithMetadata`](https://github.com/desktop/desktop/blob/75445ea6/app/src/lib/error-with-metadata.ts) -
|
2017-12-12 11:19:11 +00:00
|
|
|
Wraps an existing `Error` with additional metadata.
|
2017-07-28 20:00:39 +00:00
|
|
|
|
2017-12-12 11:19:11 +00:00
|
|
|
`ErrorWithMetadata` instances can provide a
|
2017-12-12 23:19:00 +00:00
|
|
|
[`RetryAction`](https://github.com/desktop/desktop/blob/75445ea6/app/src/lib/retry-actions.ts)
|
2017-12-12 11:19:11 +00:00
|
|
|
which gives error handlers the ability to retry whatever action caused the
|
|
|
|
error.
|