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:
![enter image description here]()
Whereas throw new Error('test error') results in:
![enter image description here]()
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
![enter image description here]()
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.