diff --git a/doc/api/errors.md b/doc/api/errors.md
index 9f82d9706c1..0298c2b1e22 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -2325,6 +2325,17 @@ compiled with ICU support.
A non-context-aware native addon was loaded in a process that disallows them.
+
+
+### `ERR_OPERATION_FAILED`
+
+
+
+An operation failed. This is typically used to signal the general failure
+of an asynchronous operation.
+
### `ERR_OUT_OF_RANGE`
@@ -2407,6 +2418,42 @@ Accessing `Object.prototype.__proto__` has been forbidden using
[`Object.setPrototypeOf`][] should be used to get and set the prototype of an
object.
+
+
+### `ERR_QUIC_CONNECTION_FAILED`
+
+
+
+> Stability: 1 - Experimental
+
+Establishing a QUIC connection failed.
+
+
+
+### `ERR_QUIC_ENDPOINT_CLOSED`
+
+
+
+> Stability: 1 - Experimental
+
+A QUIC Endpoint closed with an error.
+
+
+
+### `ERR_QUIC_OPEN_STREAM_FAILED`
+
+
+
+> Stability: 1 - Experimental
+
+Opening a QUIC stream failed.
+
### `ERR_REQUIRE_CYCLE_MODULE`
@@ -2990,6 +3037,16 @@ try {
}
```
+
+
+### `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`
+
+
+
+Type stripping is not supported for files descendent of a `node_modules` directory.
+
### `ERR_USE_AFTER_CLOSE`
@@ -3636,17 +3693,6 @@ error indicates that the idle loop has failed to stop.
A Node.js API was called in an unsupported manner, such as
`Buffer.write(string, encoding, offset[, length])`.
-
-
-### `ERR_OPERATION_FAILED`
-
-
-
-An operation failed. This is typically used to signal the general failure
-of an asynchronous operation.
-
### `ERR_OUTOFMEMORY`
@@ -3670,42 +3716,6 @@ removed: v10.0.0
The `node:repl` module was unable to parse data from the REPL history file.
-
-
-### `ERR_QUIC_CONNECTION_FAILED`
-
-
-
-> Stability: 1 - Experimental
-
-Establishing a QUIC connection failed.
-
-
-
-### `ERR_QUIC_ENDPOINT_CLOSED`
-
-
-
-> Stability: 1 - Experimental
-
-A QUIC Endpoint closed with an error.
-
-
-
-### `ERR_QUIC_OPEN_STREAM_FAILED`
-
-
-
-> Stability: 1 - Experimental
-
-Opening a QUIC stream failed.
-
### `ERR_SOCKET_CANNOT_SEND`
@@ -4097,16 +4107,6 @@ The public key in the certificate SubjectPublicKeyInfo could not be read.
An error occurred trying to allocate memory. This should never happen.
-
-
-#### `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`
-
-
-
-Type stripping is not supported for files descendent of a `node_modules` directory.
-
[ES Module]: esm.md
[ICU]: intl.md#internationalization-support
[JSON Web Key Elliptic Curve Registry]: https://www.iana.org/assignments/jose/jose.xhtml#web-key-elliptic-curve
diff --git a/test/parallel/test-eslint-documented-errors.js b/test/parallel/test-eslint-documented-errors.js
index 03131306d7d..1759c786fd0 100644
--- a/test/parallel/test-eslint-documented-errors.js
+++ b/test/parallel/test-eslint-documented-errors.js
@@ -27,11 +27,6 @@ new RuleTester().run('documented-errors', rule, {
message: `"${invalidCode}" is not documented in doc/api/errors.md`,
line: 2
},
- {
- message:
- `doc/api/errors.md does not have an anchor for "${invalidCode}"`,
- line: 2
- },
]
},
]
diff --git a/tools/eslint-rules/documented-errors.js b/tools/eslint-rules/documented-errors.js
index 17bd2221097..39021d973f2 100644
--- a/tools/eslint-rules/documented-errors.js
+++ b/tools/eslint-rules/documented-errors.js
@@ -4,35 +4,85 @@ const fs = require('fs');
const path = require('path');
const { isDefiningError } = require('./rules-utils.js');
-const doc = fs.readFileSync(path.resolve(__dirname, '../../doc/api/errors.md'),
- 'utf8');
+// Load the errors documentation file once
+const docPath = path.resolve(__dirname, '../../doc/api/errors.md');
+const doc = fs.readFileSync(docPath, 'utf8');
-function isInDoc(code) {
- return doc.includes(`### \`${code}\``);
-}
-
-function includesAnchor(code) {
- return doc.includes(``);
-}
-
-function errorForNode(node) {
- return node.expression.arguments[0].value;
+// Helper function to parse errors documentation and return a Map
+function getErrorsInDoc() {
+ const lines = doc.split('\n');
+ let currentHeader;
+ const errors = new Map();
+ const codePattern = /^### `([^`]+)`$/;
+ const anchorPattern = /^<\/a>$/;
+
+ function parse(line, legacy) {
+ const error = { legacy };
+ let code;
+
+ const codeMatch = line.match(codePattern);
+ if (codeMatch) {
+ error.header = true;
+ code = codeMatch[1];
+ }
+
+ const anchorMatch = line.match(anchorPattern);
+ if (anchorMatch) {
+ error.anchor = true;
+ code ??= anchorMatch[1];
+ }
+
+ if (!code) return;
+
+ // If the code already exists in the Map, merge the new error data
+ errors.set(code, {
+ ...errors.get(code),
+ ...error,
+ });
+ }
+
+ for (const line of lines) {
+ if (line.startsWith('## ')) currentHeader = line.substring(3);
+ if (currentHeader === 'Node.js error codes') parse(line, false);
+ if (currentHeader === 'Legacy Node.js error codes') parse(line, true);
+ }
+
+ return errors;
}
+// Main rule export
module.exports = {
- create: function(context) {
+ create(context) {
+ const errors = getErrorsInDoc();
return {
- ExpressionStatement: function(node) {
- if (!isDefiningError(node) || !errorForNode(node)) return;
- const code = errorForNode(node);
- if (!isInDoc(code)) {
- const message = `"${code}" is not documented in doc/api/errors.md`;
- context.report({ node, message });
+ ExpressionStatement(node) {
+ if (!isDefiningError(node)) return;
+
+ const code = node.expression.arguments?.[0]?.value;
+ if (!code) return;
+
+ const err = errors.get(code); // Use Map's get method to retrieve the error
+
+ if (!err || !err.header) {
+ context.report({
+ node,
+ message: `"${code}" is not documented in doc/api/errors.md`,
+ });
+ if (!err) return;
}
- if (!includesAnchor(code)) {
- const message =
- `doc/api/errors.md does not have an anchor for "${code}"`;
- context.report({ node, message });
+
+ if (!err.anchor) {
+ context.report({
+ node,
+ message: `doc/api/errors.md does not have an anchor for "${code}"`,
+ });
+ }
+
+ if (err.legacy) {
+ context.report({
+ node,
+ message: `"${code}" is marked as legacy, yet it is used in lib/.`,
+ });
}
},
};