Error Handling in Async Code
9 min read
Error Handling in Async Code
Unhandled errors in async functions can crash your Node.js process or go silently unnoticed. Robust error handling is one of the most important skills in production Node.js development.
try/catch with async/await
js
async function fetchUser(id) {
try {
const response = await fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const user = await response.json();
return user;
} catch (err) {
// Network errors, JSON parse errors, HTTP errors all land here
console.error("fetchUser failed:", err.message);
throw err; // Re-throw so callers can handle it too
}
}Global Unhandled Rejection Handler
js
process.on("unhandledRejection", function(reason, promise) {
console.error("Unhandled Promise rejection:", reason);
// In production, log to monitoring and exit cleanly
process.exit(1);
});
process.on("uncaughtException", function(err) {
console.error("Uncaught exception:", err);
process.exit(1);
});Custom Error Classes
js
class AppError extends Error {
constructor(message, statusCode = 500) {
super(message);
this.name = "AppError";
this.statusCode = statusCode;
}
}
async function getUser(id) {
if (!id) throw new AppError("User ID is required", 400);
// ...
}In Node.js 15+, unhandled Promise rejections terminate the process by default. Always add .catch() or try/catch around every await call.
Ready to test yourself?
Practice Node.js— quiz & coding exercises