jsrosetta

Error handling

Uncaught Exceptions

How Node.js's process.on('uncaughtException') compares to panic/recover (Go), catch_unwind (Rust), do/catch (Swift), and an uncaught exception handler (Java).

Minimum versions
Node.js ≥ 12.20Go ≥ 1.0Rust ≥ 1.58Swift ≥ 5.1Java ≥ 25
Verified on
Node.js 24.12.0Go 1.27.1Rust 1.98.1Swift 6.2.4Java 25.0.4.1

Node.js code is an ES module: save it as .mjs or set "type": "module" in package.json.

The error handling and try/catch post covered throw/try/catch for regular error-handling flow. This one is different: a case where an error escapes every normal handling path and flies straight to the top level — the last-resort catch before the process crashes. Rust has catch_unwind (wrapping a call, similar to Go's defer/recover). Swift has no global hook at all — wrapping your program's entry point in do/catch is the closest thing, and an Error that truly goes uncaught all the way to the top crashes the runtime immediately, with nothing to save it. Java has Thread.setDefaultUncaughtExceptionHandler() — a global hook that does exactly what its name says, just like process.on('uncaughtException').

Catching an exception at the top level (uncaughtException vs recover)

process.on("uncaughtException", (err) => {
  console.log(`caught exception: ${err.message}`); // → caught exception: my exception
  process.exit(1); // log, clean up and exit: resuming after this is unsafe
});
 
function foo() {
  throw new Error("my exception");
}
 
function main() {
  foo();
}
 
main();
// exit code: 1

Exit codes split into two groups: both JS and Java call process.exit(1)/let the main thread crash and exit with a non-zero code — both treat "caught at the top level" as a sign to stop, not to keep going. Go, Rust, and Swift all "swallow" the error with recover()/catch_unwind/do-catch and let the program return normally, so they exit with code 0.

Reference: github.com/miguelmota/golang-for-nodejs-developers#exceptions