preserve-caught-error

重新抛出自定义错误时,禁止丢失最初捕获的错误

💡 hasSuggestions

此规则报告的一些问题可通过编辑器 建议 手动修复

JavaScript 开发者经常在 catch 块中重新抛出错误以添加上下文,但忘记保留原始错误,从而导致调试信息丢失。

¥JavaScript developers often re-throw errors in catch blocks to add context but forget to preserve the original error, resulting in lost debugging information.

抛出新错误时使用 cause 选项有助于保留原始错误并维护完整的错误链,从而提高可调试性和可追溯性。

¥Using the cause option when throwing new errors helps retain the original error and maintain complete error chains, which improves debuggability and traceability.

try {
	await fetch("https://xyz.com/resource");
} catch(error) {
	// Throw a more specific error without losing original context
	throw new Error("Failed to fetch resource", {
		cause: error
	});
}

规则详情

¥Rule Details

此规则强制在 catch 块内抛出新错误时使用 cause 属性。

¥This rule enforces the use of the cause property when throwing a new error inside a catch block.

检查所有支持传递 cause 的内置 error types

¥Checks for all built-in error types that support passing a cause.

此规则的错误代码示例:

¥Examples of incorrect code for this rule:

在线运行
/* eslint preserve-caught-error: "error" */

// Not using the `cause` option
try {
    // ...
} catch (error) {
    throw new Error("Something went wrong: " + error.message);
}

// Throwing a new Error with unrelated cause
try {
	doSomething();
} catch (err) {
	const unrelated = new Error("other");
	throw new Error("Something failed", { cause: unrelated });
}

// Caught error is being lost partially due to destructuring
try {
	doSomething();
} catch ({ message, ...rest }) {
	throw new Error(message);
}

// Cause error is being shadowed by a closer scoped redeclaration.
try {
    doSomething();
} catch (error) {
    if (whatever) {
        const error = anotherError; // This declaration is the problem.
        throw new Error("Something went wrong", { cause: error });
    }
}

此规则的正确代码示例:

¥Examples of correct code for this rule:

在线运行
/* eslint preserve-caught-error: "error" */

try {
    // ...
} catch (error) {
    throw new Error("Something went wrong", { cause: error });
}

// When the thrown error is not directly related to the caught error.
try {
} catch (error) {
	foo = {
		bar() {
			// This throw is not directly related to the caught error.
			throw new Error("Something went wrong");
		}
	};
}

// No throw inside catch
try {
    doSomething();
} catch (e) {
    console.error(e);
}

// Ignoring the caught error at the parameter level
// This is valid by default, but this behavior can be changed
// by using the `requireCatchParameter` option discussed below.
try {
	doSomething();
} catch {
	throw new TypeError("Something went wrong");
}

选项

¥Options

此规则只有一个选项 - 一个具有以下可选属性的对象:

¥This rule takes a single option — an object with the following optional property:

  • requireCatchParameter:要求 catch 块在设置为 true 时始终包含已捕获的错误参数。默认情况下,这是 false

    ¥requireCatchParameter: Requires the catch blocks to always have the caught error parameter when set to true. By default, this is false.

requireCatchParameter

启用此选项要求所有 catch 块都必须包含一个已捕获的错误参数。这确保了已捕获的错误不会在参数级别被丢弃。

¥Enabling this option mandates for all the catch blocks to have a caught error parameter. This makes sure that the caught error is not discarded at the parameter level.

"preserve-caught-error": ["error", {
  "requireCatchParameter": true
}]

{ "requireCatchParameter": true } 选项的错误代码示例:

¥Example of incorrect code for the { "requireCatchParameter": true } option:

在线运行
/* eslint preserve-caught-error: ["error", { "requireCatchParameter": true }] */

try {
	doSomething();
} catch { // Can't discard the error ❌
	throw new Error("Something went wrong");
}

{ "requireCatchParameter": true } 选项的正确代码示例:

¥Example of correct code for the { "requireCatchParameter": true } option:

在线运行
/* eslint preserve-caught-error: ["error", { "requireCatchParameter": true }] */

try {
	doSomething();
} catch(error) { // Error is being referenced ✅
	// Handling and re-throw logic
}

何时不使用

¥When Not To Use It

如果你符合以下情况,则可能不想启用此规则:

¥You might not want to enable this rule if:

  • 你遵循自定义错误处理方法,其中故意从重新抛出的错误中省略原始错误(例如,为了避免暴露内部详细信息或单独记录原始错误)。

    ¥You follow a custom error-handling approach where the original error is intentionally omitted from re-thrown errors (e.g., to avoid exposing internal details or to log the original error separately).

  • 你使用第三方或内部错误处理库,该库使用非标准属性(例如 verror)而不是 cause 选项来保存错误上下文。

    ¥You use a third-party or internal error-handling library that preserves error context using non-standard properties (e.g., verror) instead of the cause option.

  • (在极少数情况下)你针对的是旧环境,其中 Error 构造函数中的 cause 选项不受支持。

    ¥(In rare cases) you are targeting legacy environments where the cause option in Error constructors is not supported.

版本

此规则是在 ESLint v9.35.0 中引入。

进阶读物

资源