preserve-caught-error
Require the caught error as the cause of a new error thrown in catch
When a catch block throws a new error, the one it caught is gone, along with its message and stack trace. The log says "Could not load the config" but not why. Pass the caught error as cause to keep both.
The rule checks throw new Error() in a catch block, and the other built-in classes such as TypeError and AggregateError. A throw in a function inside the block isn't checked.
The report comes with a suggestion that adds { cause: error }.
This rule is on by default.
Configure#
On by default as a warning. To turn it off:
[lint.rules]
"preserve-caught-error" = "off" # or "error"Every option, set to its default:
[lint.rules]
"preserve-caught-error" = ["warn", {
requireCatchParameter = false,
errorClassNames = [], # list of strings or objects
}]Examples#
try {
loadConfig();
} catch (error) {
throw new Error("Could not load the config");There is no cause attached to the symptom error being thrown.
}The cause must be the caught error itself, not a part of it:
try {
loadConfig();
} catch (error) {
throw new Error("Could not load the config", { cause: error.messageThe symptom error is being thrown with an incorrect cause. });
}Destructuring the parameter loses the rest of the error:
try {
loadConfig();
} catch ({ message }) {Re-throws cannot preserve the caught error as a part of it is being lost due to destructuring.
throw new Error(`Could not load the config: ${message}`);
}try {
loadConfig();
} catch (error) {
throw new Error("Could not load the config", { cause: error });
}
try {
saveConfig();
} catch (error) {
report(error);
throw error;
}Options#
| Option | Default | What it does |
|---|---|---|
requireCatchParameter | false | Also report a new error thrown in a catch that has no parameter. |
errorClassNames | [] | Your own error classes to check as well. |
{ "requireCatchParameter": true }1 problemtry {
loadConfig();
} catch {
throw new Error("Could not load the config");The caught error is not accessible because the catch clause lacks the error parameter. Start referencing the caught error using the catch parameter.
}Each errorClassNames entry is the name of a class that takes { cause } as its second argument, like Error:
{ "errorClassNames": ["ConfigError"] }1 problemtry {
loadConfig();
} catch (error) {
throw new ConfigError("Could not load the config");There is no cause attached to the symptom error being thrown.
}If { cause } is a different argument, make the entry an object that says which one, counting from 1:
{ "errorClassNames": [{ "name": "HttpError", "argumentPosition": 3 }] }1 problemtry {
await fetchUser(id);
} catch (error) {
throw new HttpError(502, "Could not fetch the user");There is no cause attached to the symptom error being thrown.
}{ "errorClassNames": [{ "name": "HttpError", "argumentPosition": 3 }] }No problemstry {
await fetchUser(id);
} catch (error) {
throw new HttpError(502, "Could not fetch the user", { cause: error });
}