Node's original convention is the error-first callback: `fn(err, result)`, where `err` is truthy on failure. Modern code prefers Promises/`async`-`await`, letting you use `try`/`catch`.
js
// error-first callback style
fs.readFile("config.json", (err, data) => {
if (err) return console.error("failed:", err.message);
console.log(JSON.parse(data));
});
// async/await style
try {
const data = await fs.promises.readFile("config.json", "utf8");
} catch (err) {
console.error("failed:", err.message);
}Unhandled errors are dangerous: an uncaught exception or an unhandled Promise rejection can crash the whole process. Production servers register `process.on("uncaughtException", ...)` and `process.on("unhandledRejection", ...)` as last-resort logging, then exit and let a process manager restart cleanly — they are not a substitute for handling errors where they occur.