Errors
Summary
This page describes how we handle errors in Dendron.
Any error that is throw by Dendron should extend from DendronError
.
Details
- If a function can return multiple errors, use
DendronCompositeError
to wrap up multiple errors. If you need to look into the errors inside aDendronCompositeError
, use errorsList() to grab the errors inside the composite error. - When returning errors from a server, use
error2PlainObject
to extract the common properties - When logging errors, use
stringifyError
(regularstringify
will omit fields) - If an error is non-fatal, meaning the function was able to complete despite the error (or that the error is a warning), then set the error severity to
ERROR_SEVERITY.MINOR
. Not all but some code like engine initialization will recognize this and consider the operation successful.
If you need additional well-typed information with an error, or you're trying to handle a specific type of error, you can do so by using extending the DendronError
class.
For an example see errorTypes.ts and ReloadIndex.
RespV3
Use this when working with functions that return data or an error
type RespV3 = {
error: IDendronError;
data?: never;
}
| {
error?: never;
data: T;
};
This type signature says that that the result can either contain an error
property or a data
property but never both at the same time.
This is useful when an error shortcircuits the calling function.
- NOTE: typescript isn't very smart about destructuring. for type narrowing to work, you can't destructure the argument
- bad
const {error, data} = someFunc if (error) { throw } // COMPILE ERROR data.value
- good
const resp = someFunc if (resp.error) { throw } resp.data.value
Example
// doFoo returns either an error or the data
function doFoo(): RespV3 {
...
if (error) {
return {error: new DendronError(...)}
}
return {
data: ....
}
}
function main() {
const resp = doFoo();
if (resp.error) {
// handle error...
}
// if error hasn't happened, we know `data` exists and is valid
doBar(resp.data)
}
Sentry
We use Sentry to monitor the code for exceptions. You can use Sentry by wrapping
a function using sentryReportingCallback
. For example:
export const provideCompletionItems = sentryReportingCallback(
(document: TextDocument, position: Position) => {
// ...
}
);
One issue here: the sentry wrapper cause the callback function to lose its this
value.
If you are passing a method to this function, you must bind the this
value:
class Foo {
private callback() { /* ... */ }
public setupCallback() {
const wrappedCallback = sentryReportingCallback(
this.callback.bind(this)
);
// ...
}
}
Otherwise, when the callback function is called the this
value will be undefined.
- NOTE: if you're interested about sentry initialization setttings, see ../packages/common-server/src/errorReporting.ts (Private)
API
ERROR_STATUS
These match to common errors in Dendron. You can find the full list here
ERROR_SEVERITY
/**
* Labels whether error is recoverable or not
*/
export enum ERROR_SEVERITY {
/**
* Recoverable
*/
MINOR = "minor",
/**
* Non-recoverable
*/
FATAL = "fatal",
}
Changelog
Past Discussions
Children
Backlinks