Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,14 @@ found [here][online].
<a id="nodejs-error-codes"></a>
## Node.js Error Codes

<a id="ERR_AMBIGUOUS_ARGUMENT"></a>
### ERR_AMBIGUOUS_ARGUMENT

This is triggered by the `assert` module in case e.g.,
`assert.throws(fn, message)` is used in a way that the message is the thrown
error message. This is ambiguous because the message is not verifying the error
message and will only be thrown in case no error is thrown.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking but if someone can help tighten this text up a bit, that would be good. @nodejs/documentation It communicates what it needs to, but there is room to make it a bit more clear I think. Doesn't have to happen in this PR (or at all). It could always happen at a later date.


<a id="ERR_ARG_NOT_ITERABLE"></a>
### ERR_ARG_NOT_ITERABLE

Expand Down
14 changes: 14 additions & 0 deletions lib/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const {
AssertionError,
errorCache,
codes: {
ERR_AMBIGUOUS_ARGUMENT,
ERR_INVALID_ARG_TYPE
}
} = require('internal/errors');
Expand Down Expand Up @@ -470,6 +471,19 @@ function expectsError(stackStartFn, actual, error, message) {
['Object', 'Error', 'Function', 'RegExp'],
error);
}
if (typeof actual === 'object' && actual !== null) {
if (actual.message === error) {
throw new ERR_AMBIGUOUS_ARGUMENT(
'error/message',
`The error message "${actual.message}" is identical to the message.`
);
}
} else if (actual === error) {
throw new ERR_AMBIGUOUS_ARGUMENT(
'error/message',
`The error "${actual}" is identical to the message.`
);
}
message = error;
error = null;
}
Expand Down
1 change: 1 addition & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ module.exports = exports = {
//
// Note: Node.js specific errors must begin with the prefix ERR_

E('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError);
E('ERR_ASSERTION', '%s', Error);
E('ERR_ASYNC_CALLBACK', '%s must be a function', TypeError);
Expand Down
33 changes: 31 additions & 2 deletions test/parallel/test-assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -833,13 +833,42 @@ common.expectsError(

// eslint-disable-next-line no-throw-literal
assert.throws(() => { throw undefined; }, /undefined/);
common.expectsError(
assert.throws(
// eslint-disable-next-line no-throw-literal
() => a.doesNotThrow(() => { throw undefined; }),
{
type: assert.AssertionError,
name: 'AssertionError [ERR_ASSERTION]',
code: 'ERR_ASSERTION',
message: 'Got unwanted exception.\nundefined'
}
);
}

assert.throws(
() => a.throws(
// eslint-disable-next-line no-throw-literal
() => { throw 'foo'; },
'foo'
),
{
code: 'ERR_AMBIGUOUS_ARGUMENT',
message: 'The "error/message" argument is ambiguous. ' +
'The error "foo" is identical to the message.'
}
);

assert.throws(
() => a.throws(
() => { throw new TypeError('foo'); },
'foo'
),
{
code: 'ERR_AMBIGUOUS_ARGUMENT',
message: 'The "error/message" argument is ambiguous. ' +
'The error message "foo" is identical to the message.'
}
);

// Should not throw.
// eslint-disable-next-line no-restricted-syntax, no-throw-literal
assert.throws(() => { throw null; }, 'foo');