Error Handling

When code in try {...} throws, control jumps to catch (err) {...} (the (err) is optional since ES2019), and finally {...} runs either way, even after return. Throw Error objects, not strings. Built-in subtypes: TypeError (wrong type), ReferenceError (undeclared name), SyntaxError (unparsable code or JSON), RangeError (value out of range) and URIError (bad decodeURI() input); EvalError is no longer thrown.

ES2022 added new Error(message, { cause }), so a wrapper keeps the original error as .cause. AggregateError (ES2021) holds several errors in .errors, as Promise.any() does (Promise Combinators). Error.isError(value) (ES2026) checks the internal error slot, not the prototype chain, so it recognizes errors from another realm (an iframe or worker) where instanceof Error fails.

finally, cause, AggregateError and Error.isError()JavaScriptLive
function loadConfig(text) {
  try { return JSON.parse(text); }
  catch (err) { throw new Error("Could not load configuration", { cause: err }); }
  finally { console.log("parse attempted"); }      // runs on success and on failure
}
try { loadConfig("{ bad json"); }
catch (e) { console.log(e.message, "|", e.cause.name); }
const all = new AggregateError([new RangeError("too big"), new TypeError("wrong")], "2 failed");
console.log(all.errors.length, Error.isError(all), Error.isError({ message: "x" }));

Error.isError() runs in Chrome 134 1 , Firefox 138 555 , Safari 18.4 10 and Node.js 24.3 2,131 but is not yet Baseline.