Skip to content
NewBun 1.4.5 is out. Release notes
AphrodyBun

Linter · Rules

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:

bunfig.toml
[lint.rules]
"preserve-caught-error" = "off" # or "error"

Every option, set to its default:

bunfig.toml
[lint.rules]
"preserve-caught-error" = ["warn", {
  requireCatchParameter = false,
  errorClassNames = [], # list of strings or objects
}]

Examples

Reported:

try {
  loadConfig();
} catch (error) {
  throw new Error("Could not load the config");
}

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.message });
}

Destructuring the parameter loses the rest of the error:

try {
  loadConfig();
} catch ({ message }) {
  throw new Error(`Could not load the config: ${message}`);
}

Not reported:

try {
  loadConfig();
} catch (error) {
  throw new Error("Could not load the config", { cause: error });
}

try {
  saveConfig();
} catch (error) {
  report(error);
  throw error;
}

Options

OptionDefaultWhat it does
requireCatchParameterfalseAlso report a new error thrown in a catch that has no parameter.
errorClassNames[]Your own error classes to check as well.
try {
  loadConfig();
} catch {
  throw new Error("Could not load the config");
}

Each errorClassNames entry is the name of a class that takes { cause } as its second argument, like Error:

try {
  loadConfig();
} catch (error) {
  throw new ConfigError("Could not load the config");
}

If { cause } is a different argument, make the entry an object that says which one, counting from 1:

try {
  await fetchUser(id);
} catch (error) {
  throw new HttpError(502, "Could not fetch the user");
}
try {
  await fetchUser(id);
} catch (error) {
  throw new HttpError(502, "Could not fetch the user", { cause: error });
}