Home >Web Front-end >JS Tutorial >A Hidden Gem in JavaScript Debugging: error.cause

A Hidden Gem in JavaScript Debugging: error.cause

DDD
DDDOriginal
2025-01-12 16:45:47722browse

A Hidden Gem in JavaScript Debugging: error.cause

The Challenges of Debugging

What is the biggest challenge in debugging? One of them is undoubtedly tracing the source of errors.

Imagine this scenario:

const func = () => {
  doSth('A');
  doSth('B');
};

When func throws an error, how do you identify at which step the error occurred? Was it caused by doSth('A'), doSth('B'), or func itself? Clearly, the error lacks sufficient context.

Common Solutions

A common approach to address this issue might look like this:

const func = () => {
  try {
    doSth('A');
  } catch (error) {
    throw new Error('An error from A', error);
  }
  try {
    doSth('B');
  } catch (error) {
    throw new Error('An error from B', error);
  }
};

With this approach, you can locate the source of the error more easily. However, this solution has several limitations:

  1. Loss of error details:

    If the error contains extensive information (e.g., payloads, HTTP status codes, error codes), this approach only adds the error message of doSth to the newly constructed error. Other crucial details, including the original stack trace, are lost.

  2. Decreased log readability:

    With more than two potential error points, the logs can become cluttered and difficult to interpret.

  3. Ambiguity in expressing intent:

    The code does not explicitly communicate that the new error is caused by the specific doSth function being caught, leaving room for improved code readability.

Introducing error.cause

To address these issues, ECMAScript 2022 introduced error.cause.

This feature allows developers to specify the root cause of an error when creating a new error object. By using error.cause, you can establish a chain of errors, making it easier to debug and trace the root cause of an issue.

Here’s a simple example:

try {
  // Some operation that may throw an error
} catch (error) {
  throw new Error('Something went wrong', { cause: error });
}

With this approach, you can build causal links between errors. For instance:

const func = () => {
  try {
    doSth('A');
  } catch (error) {
    throw new Error('An error from A', { cause: error });
  }
  try {
    doSth('B');
  } catch (error) {
    throw new Error('An error from B', { cause: error });
  }
};

This allows us to catch errors thrown by lower-level functions (e.g., doSth('A')), throw a new error that adds relevant context (e.g., "An error occurred while executing doSth('A')"), and preserve the original error details (e.g., "A is an illegal argument.").

Building a Chain of Errors

Another advantage of error.cause is its ability to create a chain of linked errors, enabling developers to trace issues back through multiple layers of the application:

const func = () => {
  try {
    try {
      try {
        doSth('A');
      } catch (error) {
        throw new Error('Error at depth 3', { cause: error });
      }
    } catch (error) {
      throw new Error('Error at depth 2', { cause: error });
    }
  } catch (error) {
    throw new Error('Error at depth 1', { cause: error });
  }
};

console.log(error.cause.cause); // Error at depth 3

In Node.js, errors with a cause are handled specially in the console. All related error stacks are printed:

const func = () => {
  doSth('A');
  doSth('B');
};

Conclusion

  • Debugging becomes significantly easier when you have immediate access to both the error context and details.
  • One effective way to achieve this is by adopting a "catch rethrow with context" pattern using the error.cause feature:
const func = () => {
  try {
    doSth('A');
  } catch (error) {
    throw new Error('An error from A', error);
  }
  try {
    doSth('B');
  } catch (error) {
    throw new Error('An error from B', error);
  }
};

This approach not only improves error traceability but also enhances the readability and maintainability of your code.


We are Leapcell, your top choice for deploying Node.js projects to the cloud.

A Hidden Gem in JavaScript Debugging: error.cause

Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:

Multi-Language Support

  • Develop with Node.js, Python, Go, or Rust.

Deploy unlimited projects for free

  • pay only for usage — no requests, no charges.

Unbeatable Cost Efficiency

  • Pay-as-you-go with no idle charges.
  • Example: $25 supports 6.94M requests at a 60ms average response time.

Streamlined Developer Experience

  • Intuitive UI for effortless setup.
  • Fully automated CI/CD pipelines and GitOps integration.
  • Real-time metrics and logging for actionable insights.

Effortless Scalability and High Performance

  • Auto-scaling to handle high concurrency with ease.
  • Zero operational overhead — just focus on building.

Explore more in the Documentation!

A Hidden Gem in JavaScript Debugging: error.cause

Follow us on X: @LeapcellHQ


Read on our blog

The above is the detailed content of A Hidden Gem in JavaScript Debugging: error.cause. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:Javascript HoistingNext article:Javascript Hoisting