How to assert that function throws with a specific error message - javascript

I'm using Node v18 ( with the built-in testrunner) and the package assert/strict to test that a function call throws an error with a custom error message.
I think my code should look like
assert.throws(() => myFunction(), 'content of error.message goes here');
Unfortunately I get the following error
error: 'The "error/message" argument is ambiguous. The error message "content of error.message goes here" is identical to the message.'
I also tried
assert.throws(
() => myFunction(),
error => {
assert.ok(error instanceof CustomError);
assert.strictEqual(error.message, 'content of error.message goes here');
return true;
});
and
assert.throws(myFunction, 'content of error.message goes here');
but unfortunately that didn't help. This might be a duplicate of node assert: Test error message but I don't want to pass in regular expressions because there is no need for it.
Does someone know how to fix the assertion?

From the docs, it looks like you can pass an object (and should for the OP case)...
// tests whether the thrown error has a particular message
assert.throws(myFunction, { message: 'content of error.message goes here'});

From the docs:
https://nodejs.org/api/assert.html#strict-assertion-mode
error cannot be a string. If a string is provided as the second argument, then error is assumed to be omitted and the string will be used for message instead. This can lead to easy-to-miss mistakes. Using the same message as the thrown error message is going to result in an ERR_AMBIGUOUS_ARGUMENT error. Please read the example below carefully if using a string as the second argument gets considered:
and
function throwingSecond() {
throw new Error('Second');
}
If it was intended to match for the error message do this instead:
It does not throw because the error messages match.
assert.throws(throwingSecond, /Second$/);

Related

Expect expression not to throw any error using Chai

I have a function
export function getFileContent(path: string): any {
const content = readFileSync(path);
return JSON.parse(content.toString());
}
If I want to check if the expression getFileContent(meteFile) throws some definite error I should write something like
expect(getFileContent(meteFile)).to.throw(new SyntaxError('Unexpected token } in JSON at position 82'));
But is there a way to check if the expression doesn't raise any error?
I tried this
expect(getFileContent(metaFile)).not.to.throw();
But got the error
AssertionError: expected { Object (...) } to be a function
So how can I check if the function call doesn't throw any error?
You can check if the function call doesn't throw an error using
assert.doesNotThrow method
Here is an example from the documentation
assert.doesNotThrow(fn, 'Any Error thrown must not have this message');
assert.doesNotThrow(fn, /Any Error thrown must not match this/);
assert.doesNotThrow(fn, Error);
assert.doesNotThrow(fn, errorInstance);
For further understanding checkout it's documentation: assert.doesNotThrow
It seems like you are using expect, so then you can use expect(fn).to.not.throw to make sure it doesn't throw an error.
expect(myFn).to.not.throw(); // makes sure no errors are thrown
expect(myFn).to.not.throw(SomeCustomError, "the message I expect in that error"); // not recommended by their docs
You should probably look at the docs for this.

What does it mean an object starts with an array in javascript

Sometimes I got an error like this which fired from catch(err => console.log(err)):
{ [Error: SQLITE_ERROR: no such table: table_name] errno: 1, code: 'SQLITE_ERROR' }
It looks like an object and yeah it is, but why is there an array in the beginning of it?
How can I get that array?
I want to get that error message:
Error: SQLITE_ERROR: no such table: table_name
To decide what to do next.
I thought the error message was part of the key name so I tried:
Object.keys(err);
But return an array like this:
["errno", "code"]
How to get that error message?
IIRC.... sqlite uses the built in Error object. What you see in brackets is not an array; it is actually a human-readable error description string which is in brackets (perhaps for emphasis).
try {
....
} catch (err) {
console.log(err.message); // this should be your error message.
}
Whatever is throwing the error is not throwing a simple string. Try a different logging method to get a better idea of what is being returned, as console.log may not be giving you the correct value of the error when being logged.
Try using console.log(JSON.parse(JSON.stringify(error))) and see what is returned. It may be that you need to do something like console.log(error.response.message) or something similar to get a more useful string you can use.
console.log may also be running a custom toString method on the returned object, like this, for example: https://repl.it/#Twinbird24/WingedCloudyTrials

try-catch statement interrupt try-block as soon as exception is thrown

Research:
According to MDN web docs :
The try...catch statement marks a block of statements to try, and
specifies a response, should an exception be thrown.
If I understand this correctly the entire try-block will be executed. This SO post confirmed myself.
My Question:
Is it possible to interrupt a try-block as soon as an exception is thrown to get into the catch-block?
Yes: How would this behavior be achieved?
No: Are there other ways to achieve this behavior?
try {
console.log('omg');
throw new Error('omg');
console.log('ahhhhhh!!!!!');
} catch {
console.log('caught');
}
I think JS does what you want. The linked SO is for Java.
The SO post you linked is about Java, not Javascript.
So the answers there might not be applicable.
As far as I know, the catch block will get triggered the moment an error is thrown.
And you can throw an error any time you want:
try {
console.log( 'before error: this should log' );
throw new Error( 'Trigger catch!' );
console.log( 'after error: this should not log' );
}
catch( error ) {
console.log( `catch block got the error: ${ error.message }` );
}

throw vs throw new Error [duplicate]

I want to write a common error handler which will catch custom errors thrown on purpose at any instance of the code.
When I did throw new Error('sample') like in the following code
try {
throw new Error({'hehe':'haha'});
// throw new Error('hehe');
} catch(e) {
alert(e);
console.log(e);
}
Log shows in Firefox as Error: [object Object] and I couldn’t parse the object.
For the second throw the log shows as: Error: hehe
Whereas when I did
try {
throw ({'hehe':'haha'});
} catch(e) {
alert(e);
console.log(e);
}
the console showed as: Object { hehe="haha"} in which I was able to access the error properties.
What is the difference?
Is the difference as seen in the code? Like string will be just passed as string and object as objects but the syntax will be different?
I haven’t explored throwing error object… I had done only throwing strings.
Is there any other way than the above two mentioned methods?
The difference between 'throw new Error' and 'throw someObject' in javascript is that throw new Error wraps the error passed to it in the following format −
{ name: 'Error', message: 'String you pass in the constructor'
}
The throw someObject will throw the object as is and will not allow any further code execution from the try block, ie same as throw new Error.
Here is a good explanation about The Error object and throwing your own errors
The Error Object
Just what we can extract from it in an event of an error? The Error object in all browsers support the following two properties:
name: The name of the error, or more specifically, the name of the constructor function the error belongs to.
message: A description of the error, with this description varying depending on the browser.
Six possible values can be returned by the name property, which as mentioned correspond to the names of the error's constructors. They are:
Error Name Description
EvalError An error in the eval() function has occurred.
RangeError Out of range number value has occurred.
ReferenceError An illegal reference has occurred.
SyntaxError A syntax error within code inside the eval() function has occurred.
All other syntax errors are not caught by try/catch/finally, and will
trigger the default browser error message associated with the error.
To catch actual syntax errors, you may use the onerror event.
TypeError An error in the expected variable type has occurred.
URIError An error when encoding or decoding the URI has occurred
(ie: when calling encodeURI()).
Throwing your own errors (exceptions)
Instead of waiting for one of the 6 types of errors to occur before control is automatically transferred from the try block to the catch block, you can also explicitly throw your own exceptions to force that to happen on demand. This is great for creating your own definitions of what an error is and when control should be transferred to catch.
throw "I'm Evil"
throw will terminate the further execution & expose message string on catch the error.
try {
throw "I'm Evil"
console.log("You'll never reach to me", 123465)
} catch (e) {
console.log(e); // I'm Evil
}
Console after throw will never be reached cause of termination.
throw new Error("I'm Evil")
throw new Error exposes an error event with two params name & message. It also terminate further execution
try {
throw new Error("I'm Evil")
console.log("You'll never reach to me", 123465)
} catch (e) {
console.log(e.name, e.message); // Error I'm Evil
}
throw Error("I'm Evil")
And just for completeness, this works also, though is not technically the correct way to do it -
try {
throw Error("I'm Evil")
console.log("You'll never reach to me", 123465)
} catch (e) {
console.log(e.name, e.message); // Error I'm Evil
}
console.log(typeof(new Error("hello"))) // object
console.log(typeof(Error)) // function
The following article perhaps goes into some more detail as to which is a better choice; throw 'An error' or throw new Error('An error'):
http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/
It suggests that the latter (new Error()) is more reliable, since browsers like Internet Explorer and Safari (unsure of versions) don't correctly report the message when using the former.
Doing so will cause an error to be thrown, but not all browsers respond the way you’d expect. Firefox, Opera, and Chrome each display an “uncaught exception” message and then include the message string. Safari and Internet Explorer simply throw an “uncaught exception” error and don’t provide the message string at all. Clearly, this is suboptimal from a debugging point of view.
TLDR: they are equivalent Error(x) === new Error(x).
// this:
const x = Error('I was created using a function call!');
​​​​// has the same functionality as this:
const y = new Error('I was constructed via the "new" keyword!');
source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
throw and throw Error are functionally equivalent. But when you catch them and serialize them to console.log they are not serialized exactly the same way:
throw 'Parameter is not a number!';
throw new Error('Parameter is not a number!');
throw Error('Parameter is not a number!');
Console.log(e) of the above will produce 2 different results:
Parameter is not a number!
Error: Parameter is not a number!
Error: Parameter is not a number!
You first mention this code:
throw new Error('sample')
and then in your first example you write:
throw new Error({'hehe':'haha'})
The first Error object would actually be useful, because it is expecting a string value, in this case 'sample'. The second would not because you are trying to pass an object in, and it is expecting a string, and would not display a helpful error.
The error object would have the "message" property, which would be 'sample'.
The Error constructor is used to create an error object. Error objects are thrown when runtime errors occur. The Error object can also be used as a base object for user-defined exceptions.
User-defined Errors are thrown via the throw statement. program control will be passed to the first catch block in the call stack.
The difference between throwing an error with and without Error object:
throw {'hehe':'haha'};
In chrome devtools looks like this:
Chrome tells us that we have an uncaught error which just is a JS object. The object itself could have information regarding the error but we still don't know immediately where it came from. Not very useful when we are working on our code and debugging it.
throw new Error({'hehe':'haha'});
In chrome devtools looks like this:
An error thrown with the Error object gives us a stack trace when we expand it. This gives us valuable information where the error precisely came from which is often valuable information when debugging your code. Further note that the error says [object Object], this is because the Error constructor expects a message string as a first argument. When it receives a object it will coerce it into a string.
you can throw as object
throw ({message: 'This Failed'})
then for example in your try/catch
try {
//
} catch(e) {
console.log(e); //{message: 'This Failed'}
console.log(e.message); //This Failed
}
or just throw a string error
throw ('Your error')
try {
//
} catch(e) {
console.log(e); //Your error
}
throw new Error //only accept a string
TLDR
throw new Error('problem') captures a number of properties of the place where the error happened.
throw 'problem' does not
new Error('message') captures the execution stack + others
Using an Error object allows you to capture the execution stack at the point where you throw the error. So when the error gets passed up the error handling tree, so does this stack snapshot.
So inserting throw "test error" somewhere in my codebase results in:
Whereas throw new Error('test error') results in:
You can see that the native Error object captures the stack at the point I throw the error and makes it available to whatever captures the error. That makes it easier for me to trace the problem when I'm debugging it.
In addition to that it also captures properties such as fileName, lineNumber and columnNumber.
If you use the stack trace it's there for exception trackers to log for you
In this case the stack is being printed into the browser console but if you're using Javascript error logging tools like Appsignal or Bugsnag then that stack will also be available in them too. If you inspect the error object you can access the stack snapshot directly:
err = new Error('test')
err.stack
The heuristic I use for deciding which format to use
When I don't plan to catch the exception I use new Error('problem')
When I'm throwing an error because something unexpected or out-of-bounds has happened in the application, let's say the local datastore is corrupted, I might be in a situation where I don't want to handle it, but I do want to flag it. In this case I'll use the Error object so I have that stack snapshot.
By using throw new Error('Datastore is corrupted') it's easier to trace my way back to what's happened.
When I plan to catch the exception I use throw 'problem'
Edit - on re-reading this I think the next part needs some caution. It's generally a good idea to be very specific about which error you choose to catch otherwise you can end up catching things that you really wanted to bubble all the way up. In general it's probably better to create a specific error type and catch that specific error (or message string). This allows errors you didn't anticipate to bubble up to the surface."
If the error is an expected error that I plan to catch and handle then I'm not going to get much use out of the stack snapshot.
So, let's say I use an http service and it returns a 500 HTTP code. I may treat this as an error which I throw "responseCode=500" and then subsequently catch and handle.
React behavior
Apart from the rest of the answers, I would like to show one difference in React.
If I throw a new Error() and I am in development mode, I will get an error screen and a console log. If I throw a string literal, I will only see it in the console and possibly miss it, if I am not watching the console log.
Example
Throwing an error logs into the console and shows an error screen while in development mode (the screen won't be visible in production).
throw new Error("The application could not authenticate.");
Whereas the following code only logs into the console:
throw "The application could not authenticate.";
The Error class includes debugging information (as properties of its instances), such as the error's call stack. JS interpreters know how to serialise those properties into an informative error message string, and they can also be consumed by debugging software - such as browser dev tools - to construct a more informative GUI representation of the error. This is why it's generally more useful to throw an instance of the Error class rather than simply throwing, for example, a string describing the error, or a number representing an error code.
Using custom errors
It's particularly useful to make your own subclasses of Error, which allow you to uniquely identify different types of error with a descriptive name and machine-readable...
clues for debugging,
information for better user-facing error messages, or
information to help recover from the error.
Then, when you're handling errors, you can use the nice and clean instanceof operator to check what kind of error occurred. e.g.:
class ShoesTooBig extends Error {}
class DangerousWaterCurrent extends Error {
constructor(waterSpeed){
super(`These waters are moving at ${waterSpeed} metres per second - too fast to cross!`) // Provide a `message` argument to the Error() constructor
this.waterSpeed = waterSpeed // This passes some context about why/how the error occurred back to whichever function is going to catch & handle it
}
}
// ...later...
try {
swimAcrossRiver(footwear, river)
} catch (thrownValue) {
if (thrownValue instanceof DangerousWaterCurrent) {
constructDam(river, thrownValue.waterSpeed)
} else {
throw thrownValue // "Re-throw" the error back up the execution chain, for someone else to handle
}
}
new Error() vs Error()
There is a "convenient" shorthand way to make an instance of Error: by calling Error(message), instead of new Error(message), the way you'd make an instance of a normal class. This is a deliberate exception, inserted by the language designers, to the rule. There are similar shorthands for other in-language classes, like Number() and String(). They also let you call these classes with () as if they were functions, not classes. JS doesn't allow normal classes to do this, even though they're all actually functions under the syntactical sugar of "classes". Try in a REPL:
> class E extends Error {}
undefined
> Error(); 'a value'
"a value"
> E(); 'a value'
Uncaught TypeError: Class constructor E cannot be invoked without 'new'
at <anonymous>:2:1
Personally, I think this design decision was a mistake, as it adds more exceptions to the rules of JavaScript - which means more to learn for programmers, and more for language translators/interpreters to account for. Instead of C++/Java's new keyword, simply calling a class as if it were a function (as in Number("abc123")) should have the properties that the new keyword currently has: the class's constructor function should be executed, with this bound to the instance. The new keyword could then be discarded from the language. This is how Python's syntax works, and it's simpler, more readable, and more convenient.
This is quite old but hopefully, anyone searching this can still learn from this:
First and famous, in javascript, we have something called Primitive Wrapper; a primitive wrapper takes primitive data and represents it in an object format by simply using the "constructor pattern". Still yet, in primitive wrappers, you can decide to have your data returned as an object type or you can have it returned as its primitive type(in this situation, you are now given a go-ahead command for javascript to extract the primitive value and in this case, you don't use the new keyword).
In Summary:
throw "My error": this creates an Error object and returns the primitive data extracted from the constructor "this" object. And if you try checking the typeof in the catch block, it tells you its a primitive typeof "string"
throw new Error("My error"): this returns you an object where you can access the error value from the message property. What simply happens here is that the "new keyword" constructs a "this" object and assign "{name:"Error",message:"..."}" to it and returns it. And when you try to check the typeof from the catch block, you will see a typeof "object".
Note: in a situation where you explicitly pass in a custom object to the throw, it will behave as if you invoked the constructor using the new keyword and therefore, the catch block will return you the custom object and not the message property value. For example: throw {name:"RangeError",message:"range is out of scope",environment:"Happened in testing function"}.
In conclusion, use whatever suits you ones you know what you are doing. But for me if i don't need much data but rather just the error, then I go for Primitive returner.
throw something works with both object and strings.But it is less supported than the other method.throw new Error("") Will only work with strings and turns objects into useless [Object obj] in the catch block.
throw new Error() is good for throwing a specified error. But if you want to do custom error handling, it's better to use throw { example: 'error' } .
That is, if you want to know the specified error, use throw new Error("example string") , if you want to handle the error in custom, use throw.
function makeErrorResponse(err = {}, httpStatus, status, message, message) {
const error = new Error();
error.httpStatus = httpStatus;
error.status = status;
error.message = message;
error.err = err;
return error;
}
throw makeErrorResponse({}, 500, 500, 'server error');

What is the error contract for functions from "fs" in Node?

In my app, written in JavaScript for Node, I wan't to try to recover from file system errors. In order to do that I need to know what that error can be. The manual doesn't say much. So my question is:
What is the contract for the error object? What can that error object be?
Example:
readFile('file/path', function (error, data) {
if (error) throw error;
console.log(data);
});
All errors returned are inherited from the JavaScript Error Object (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error), and fall into two categories: JS errors and system errors.
Single operation APIs such as the readFile method in your example return either null, if there is no error, or an Error instance (https://nodejs.org/api/errors.html). Common system errors such as Permission Denied or No Such File can be returned, and an exhaustive list can be found here:
http://man7.org/linux/man-pages/man3/errno.3.html
There is plenty of documentation, you just need to be careful to catch the errors properly, especially when using async methods.
Errors are instances of the JS object and have properties. You can do something like:
if (e.code === 'EISDIR') {
console.log("Is not a directory!");
} else {
throw e;
}
Check out the docs here for the Node Error object.
Error
Typically it'll have a message and stack property. The message property is a detailed message about the error that was thrown. stack is the stack trace at the point when the error was thrown.
Some developers also put custom properties to add more details about the error. Hope this helps.

Categories