Skip to content

Commit 4b82d89

Browse files
apapirovskiaddaleax
authored andcommitted
errors: consistent format for error message
Consistently use printf-style strings for error messages that do not need a custom argument order or processing of arguments. PR-URL: nodejs#16904 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 2c0acc0 commit 4b82d89

3 files changed

Lines changed: 93 additions & 41 deletions

File tree

lib/internal/errors.js

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint documented-errors: "error" */
22
/* eslint alphabetize-errors: "error" */
3+
/* eslint prefer-util-format-errors: "error" */
34

45
'use strict';
56

@@ -222,8 +223,8 @@ module.exports = exports = {
222223

223224
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable');
224225
E('ERR_ASSERTION', '%s');
225-
E('ERR_ASYNC_CALLBACK', (name) => `${name} must be a function`);
226-
E('ERR_ASYNC_TYPE', (s) => `Invalid name for async "type": ${s}`);
226+
E('ERR_ASYNC_CALLBACK', '%s must be a function');
227+
E('ERR_ASYNC_TYPE', 'Invalid name for async "type": %s');
227228
E('ERR_BUFFER_OUT_OF_BOUNDS', bufferOutOfBounds);
228229
E('ERR_BUFFER_TOO_LARGE',
229230
`Cannot create a Buffer larger than 0x${kMaxLength.toString(16)} bytes`);
@@ -247,12 +248,10 @@ E('ERR_CRYPTO_INVALID_STATE', 'Invalid state for operation %s');
247248
E('ERR_CRYPTO_SIGN_KEY_REQUIRED', 'No key provided to sign');
248249
E('ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH',
249250
'Input buffers must have the same length');
250-
E('ERR_DNS_SET_SERVERS_FAILED', (err, servers) =>
251-
`c-ares failed to set servers: "${err}" [${servers}]`);
251+
E('ERR_DNS_SET_SERVERS_FAILED', 'c-ares failed to set servers: "%s" [%s]');
252252
E('ERR_ENCODING_INVALID_ENCODED_DATA',
253-
(enc) => `The encoded data was not valid for encoding ${enc}`);
254-
E('ERR_ENCODING_NOT_SUPPORTED',
255-
(enc) => `The "${enc}" encoding is not supported`);
253+
'The encoded data was not valid for encoding %s');
254+
E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported');
256255
E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value');
257256
E('ERR_HTTP2_CONNECT_AUTHORITY',
258257
':authority header is required for CONNECT requests');
@@ -272,10 +271,9 @@ E('ERR_HTTP2_HEADERS_AFTER_RESPOND',
272271
'Cannot specify additional headers after response initiated');
273272
E('ERR_HTTP2_HEADERS_OBJECT', 'Headers must be an object');
274273
E('ERR_HTTP2_HEADERS_SENT', 'Response has already been initiated.');
275-
E('ERR_HTTP2_HEADER_REQUIRED',
276-
(name) => `The ${name} header is required`);
274+
E('ERR_HTTP2_HEADER_REQUIRED', 'The %s header is required');
277275
E('ERR_HTTP2_HEADER_SINGLE_VALUE',
278-
(name) => `Header field "${name}" must have only a single value`);
276+
'Header field "%s" must have only a single value');
279277
E('ERR_HTTP2_INFO_HEADERS_AFTER_RESPOND',
280278
'Cannot send informational headers after the HTTP message has been sent');
281279
E('ERR_HTTP2_INFO_STATUS_NOT_ALLOWED',
@@ -284,44 +282,40 @@ E('ERR_HTTP2_INVALID_CONNECTION_HEADERS',
284282
'HTTP/1 Connection specific headers are forbidden: "%s"');
285283
E('ERR_HTTP2_INVALID_HEADER_VALUE', 'Invalid value "%s" for header "%s"');
286284
E('ERR_HTTP2_INVALID_INFO_STATUS',
287-
(code) => `Invalid informational status code: ${code}`);
285+
'Invalid informational status code: %s');
288286
E('ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH',
289287
'Packed settings length must be a multiple of six');
290288
E('ERR_HTTP2_INVALID_PSEUDOHEADER',
291-
(name) => `"${name}" is an invalid pseudoheader or is used incorrectly`);
289+
'"%s" is an invalid pseudoheader or is used incorrectly');
292290
E('ERR_HTTP2_INVALID_SESSION', 'The session has been destroyed');
293291
E('ERR_HTTP2_INVALID_SETTING_VALUE',
294-
(name, value) => `Invalid value for setting "${name}": ${value}`);
292+
'Invalid value for setting "%s": %s');
295293
E('ERR_HTTP2_INVALID_STREAM', 'The stream has been destroyed');
296294
E('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK',
297-
(max) => `Maximum number of pending settings acknowledgements (${max})`);
295+
'Maximum number of pending settings acknowledgements (%s)');
298296
E('ERR_HTTP2_NO_SOCKET_MANIPULATION',
299297
'HTTP/2 sockets should not be directly manipulated (e.g. read and written)');
300298
E('ERR_HTTP2_OUT_OF_STREAMS',
301299
'No stream ID is available because maximum stream ID has been reached');
302300
E('ERR_HTTP2_PAYLOAD_FORBIDDEN',
303-
(code) => `Responses with ${code} status must not have a payload`);
301+
'Responses with %s status must not have a payload');
304302
E('ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED', 'Cannot set HTTP/2 pseudo-headers');
305303
E('ERR_HTTP2_PUSH_DISABLED', 'HTTP/2 client has disabled push streams');
306304
E('ERR_HTTP2_SEND_FILE', 'Only regular files can be sent');
307305
E('ERR_HTTP2_SOCKET_BOUND',
308306
'The socket is already bound to an Http2Session');
309307
E('ERR_HTTP2_STATUS_101',
310308
'HTTP status code 101 (Switching Protocols) is forbidden in HTTP/2');
311-
E('ERR_HTTP2_STATUS_INVALID',
312-
(code) => `Invalid status code: ${code}`);
309+
E('ERR_HTTP2_STATUS_INVALID', 'Invalid status code: %s');
313310
E('ERR_HTTP2_STREAM_CLOSED', 'The stream is already closed');
314-
E('ERR_HTTP2_STREAM_ERROR',
315-
(code) => `Stream closed with error code ${code}`);
311+
E('ERR_HTTP2_STREAM_ERROR', 'Stream closed with error code %s');
316312
E('ERR_HTTP2_STREAM_SELF_DEPENDENCY', 'A stream cannot depend on itself');
317-
E('ERR_HTTP2_UNSUPPORTED_PROTOCOL',
318-
(protocol) => `protocol "${protocol}" is unsupported.`);
313+
E('ERR_HTTP2_UNSUPPORTED_PROTOCOL', 'protocol "%s" is unsupported.');
319314
E('ERR_HTTP_HEADERS_SENT',
320315
'Cannot %s headers after they are sent to the client');
321316
E('ERR_HTTP_INVALID_CHAR', 'Invalid character in statusMessage.');
322317
E('ERR_HTTP_INVALID_HEADER_VALUE', 'Invalid value "%s" for header "%s"');
323-
E('ERR_HTTP_INVALID_STATUS_CODE',
324-
(originalStatusCode) => `Invalid status code: ${originalStatusCode}`);
318+
E('ERR_HTTP_INVALID_STATUS_CODE', 'Invalid status code: %s');
325319
E('ERR_HTTP_TRAILER_INVALID',
326320
'Trailers are invalid with this transfer encoding');
327321
E('ERR_INDEX_OUT_OF_RANGE', 'Index out of range');
@@ -330,16 +324,14 @@ E('ERR_INSPECTOR_CLOSED', 'Session was closed');
330324
E('ERR_INSPECTOR_NOT_AVAILABLE', 'Inspector is not available');
331325
E('ERR_INSPECTOR_NOT_CONNECTED', 'Session is not connected');
332326
E('ERR_INVALID_ARG_TYPE', invalidArgType);
333-
E('ERR_INVALID_ARG_VALUE',
334-
(name, value) => {
335-
return `The value "${String(value)}" is invalid for argument "${name}"`;
336-
});
327+
E('ERR_INVALID_ARG_VALUE', (name, value) =>
328+
`The value "${String(value)}" is invalid for argument "${name}"`);
337329
E('ERR_INVALID_ARRAY_LENGTH',
338330
(name, len, actual) => {
339331
internalAssert(typeof actual === 'number', 'actual must be a number');
340332
return `The array "${name}" (length ${actual}) must be of length ${len}.`;
341333
});
342-
E('ERR_INVALID_ASYNC_ID', (type, id) => `Invalid ${type} value: ${id}`);
334+
E('ERR_INVALID_ASYNC_ID', 'Invalid %s value: %s');
343335
E('ERR_INVALID_BUFFER_SIZE', 'Buffer size must be a multiple of %s');
344336
E('ERR_INVALID_CALLBACK', 'Callback must be a function');
345337
E('ERR_INVALID_CHAR', invalidChar);
@@ -354,15 +346,12 @@ E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s');
354346
E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent');
355347
E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]');
356348
E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s');
357-
E('ERR_INVALID_OPT_VALUE',
358-
(name, value) => {
359-
return `The value "${String(value)}" is invalid for option "${name}"`;
360-
});
349+
E('ERR_INVALID_OPT_VALUE', (name, value) =>
350+
`The value "${String(value)}" is invalid for option "${name}"`);
361351
E('ERR_INVALID_OPT_VALUE_ENCODING',
362-
(value) => `The value "${String(value)}" is invalid for option "encoding"`);
352+
'The value "%s" is invalid for option "encoding"');
363353
E('ERR_INVALID_PERFORMANCE_MARK', 'The "%s" performance mark has not been set');
364-
E('ERR_INVALID_PROTOCOL', (protocol, expectedProtocol) =>
365-
`Protocol "${protocol}" not supported. Expected "${expectedProtocol}"`);
354+
E('ERR_INVALID_PROTOCOL', 'Protocol "%s" not supported. Expected "%s"');
366355
E('ERR_INVALID_REPL_EVAL_CONFIG',
367356
'Cannot specify both "breakEvalOnSigint" and "eval" for REPL');
368357
E('ERR_INVALID_SYNC_FORK_INPUT',
@@ -402,8 +391,7 @@ E('ERR_SOCKET_BAD_BUFFER_SIZE', 'Buffer size must be a positive integer');
402391
E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536. Received %s.');
403392
E('ERR_SOCKET_BAD_TYPE',
404393
'Bad socket type specified. Valid types are: udp4, udp6');
405-
E('ERR_SOCKET_BUFFER_SIZE',
406-
(reason) => `Could not get or set buffer size: ${reason}`);
394+
E('ERR_SOCKET_BUFFER_SIZE', 'Could not get or set buffer size: %s');
407395
E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data');
408396
E('ERR_SOCKET_CLOSED', 'Socket is closed');
409397
E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running');
@@ -419,8 +407,7 @@ E('ERR_STREAM_WRITE_AFTER_END', 'write after end');
419407
E('ERR_SYSTEM_ERROR', sysError('A system error occurred'));
420408
E('ERR_TLS_CERT_ALTNAME_INVALID',
421409
'Hostname/IP does not match certificate\'s altnames: %s');
422-
E('ERR_TLS_DH_PARAM_SIZE', (size) =>
423-
`DH parameter size ${size} is less than 2048`);
410+
E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048');
424411
E('ERR_TLS_HANDSHAKE_TIMEOUT', 'TLS handshake timeout');
425412
E('ERR_TLS_RENEGOTIATION_FAILED', 'Failed to renegotiate');
426413
E('ERR_TLS_REQUIRED_SERVER_NAME',
@@ -430,8 +417,7 @@ E('ERR_TRANSFORM_ALREADY_TRANSFORMING',
430417
'Calling transform done when still transforming');
431418
E('ERR_TRANSFORM_WITH_LENGTH_0',
432419
'Calling transform done when writableState.length != 0');
433-
E('ERR_UNESCAPED_CHARACTERS',
434-
(name) => `${name} contains unescaped characters`);
420+
E('ERR_UNESCAPED_CHARACTERS', '%s contains unescaped characters');
435421
E('ERR_UNHANDLED_ERROR',
436422
(err) => {
437423
const msg = 'Unhandled error.';
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
3+
/* eslint-disable no-template-curly-in-string */
4+
5+
require('../common');
6+
7+
const RuleTester = require('../../tools/eslint').RuleTester;
8+
const rule = require('../../tools/eslint-rules/prefer-util-format-errors');
9+
10+
new RuleTester({ parserOptions: { ecmaVersion: 6 } })
11+
.run('prefer-util-format-errors', rule, {
12+
valid: [
13+
'E(\'ABC\', \'abc\');',
14+
'E(\'ABC\', (arg1, arg2) => `${arg2}${arg1}`);',
15+
'E(\'ABC\', (arg1, arg2) => `${arg1}{arg2.something}`);',
16+
'E(\'ABC\', (arg1, arg2) => fn(arg1, arg2));'
17+
],
18+
invalid: [
19+
{
20+
code: 'E(\'ABC\', (arg1, arg2) => `${arg1}${arg2}`);',
21+
errors: [{
22+
message: 'Please use a printf-like formatted string that ' +
23+
'util.format can consume.'
24+
}]
25+
}
26+
]
27+
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
'use strict';
2+
3+
const errMsg = 'Please use a printf-like formatted string that util.format' +
4+
' can consume.';
5+
6+
function isArrowFunctionWithTemplateLiteral(node) {
7+
return node.type === 'ArrowFunctionExpression' &&
8+
node.body.type === 'TemplateLiteral';
9+
}
10+
11+
function isDefiningError(node) {
12+
return node.expression &&
13+
node.expression.type === 'CallExpression' &&
14+
node.expression.callee &&
15+
node.expression.callee.name === 'E';
16+
}
17+
18+
module.exports = {
19+
create: function(context) {
20+
return {
21+
ExpressionStatement: function(node) {
22+
if (!isDefiningError(node))
23+
return;
24+
25+
const msg = node.expression.arguments[1];
26+
if (!isArrowFunctionWithTemplateLiteral(msg))
27+
return;
28+
29+
const { expressions } = msg.body;
30+
const hasSequentialParams = msg.params.every((param, index) => {
31+
const expr = expressions[index];
32+
return expr && expr.type === 'Identifier' && param.name === expr.name;
33+
});
34+
if (hasSequentialParams)
35+
context.report(msg, errMsg);
36+
}
37+
};
38+
}
39+
};

0 commit comments

Comments
 (0)