🚨 How to Handle Unhandled Exceptions & Unhandled Promise Rejections in JavaScript and React
One of the biggest differences between a demo app and a production app is error handling.
A good application doesn't just work when everything is fine—it fails gracefully when something goes wrong.
🧠 1️⃣ What is an Unhandled Exception?
An unhandled exception is an error that is thrown but never caught.
Example:
function divide(a, b) {
if (b === 0) {
throw new Error("Cannot divide by zero");
}
return a / b;
}
divide(10, 0); // ❌ Uncaught Error
Since there's no try...catch, the application may crash or stop executing that code path.
✅ Handle It with try...catch
try {
divide(10, 0);
} catch (error) {
console.error(error.message);
}
✔ Prevents the app from crashing unexpectedly.
🧠 2️⃣ What is an Unhandled Promise Rejection?
When a Promise rejects and no .catch() (or try...catch with await) handles it.
fetch("/api/users")
.then(res => res.json());
// ❌ No .catch()
Or:
async function getUsers() {
const res = await fetch("/api/users");
return res.json();
}
// ❌ No try...catch
✅ Handle Async Errors Properly
async function getUsers() {
try {
const res = await fetch("/api/users");
if (!res.ok) {
throw new Error("Failed to fetch users");
}
return await res.json();
} catch (error) {
console.error(error);
}
}
⚛️ 3️⃣ Handling Errors in React
React Error Boundaries catch:
✔ Rendering errors
✔ Lifecycle errors
✔ Constructor errors
Example:
<ErrorBoundary>
<Dashboard />
</ErrorBoundary>
🚨 Error Boundaries DO NOT Catch
❌ Event handler errors
<button onClick={() => {
throw new Error("Boom");
}} />
❌ Async errors
setTimeout(() => {
throw new Error("Boom");
}, 1000);
❌ Promise rejections
You must handle these yourself.
🌐 4️⃣ Global Error Handling (Browser)
You can listen for uncaught JavaScript errors:
window.addEventListener("error", (event) => {
console.error("Unhandled Exception:", event.error);
});
Useful for:
- Logging
- Monitoring
- Crash reporting
🌐 5️⃣ Global Promise Rejection Handling
Handle promises that nobody caught:
window.addEventListener("unhandledrejection", (event) => {
console.error("Unhandled Promise:", event.reason);
});
This is commonly used to send errors to monitoring tools.
📊 6️⃣ Log Errors to Monitoring Services
In production, don't just use:
console.error(error);
Use tools like:
- Sentry
- Bugsnag
- Datadog
These provide:
✔ Stack traces
✔ User sessions
✔ Browser info
✔ Release tracking
🚨 Common Mistakes
❌ Empty catch blocks
try {
// code
} catch {}
👉 Silently ignores errors.
❌ Swallowing errors
catch (error) {
// do nothing
}
Always log or handle them appropriately.
❌ Assuming fetch() throws for HTTP errors
const res = await fetch("/users");
A 404 or 500 does not throw. You should check:
if (!res.ok) {
throw new Error("Request failed");
}
💡 Senior-Level Insight
A good error-handling strategy has multiple layers:
Local handling:try...catchfor recoverable operations.
Component handling: Error Boundaries for UI rendering errors.
Global handling:window.onerrorandwindow.onunhandledrejection.
Monitoring: Send errors to a centralized service instead of relying onconsole.error.
The goal isn't to hide errors—it's to capture them, recover when possible, and give users a graceful experience.
🎯 Interview One-Liner
Handle synchronous exceptions using
try...catch, asynchronous errors using.catch()ortry...catchwithasync/await, use React Error Boundaries for rendering errors, and implement global error listeners and monitoring tools to capture uncaught exceptions and promise rejections in production.
SOCIAL SHARE CARD GENERATOR