How to Fix 'Unhandled Promise Rejection' in JavaScript
The Error
Unhandled Promise Rejection: Error: API request failed
Unhandled Promise Rejection: TypeError: Cannot read properties of undefined
(node:12345) UnhandledPromiseRejectionWarning: Error: ...This warning (or error in Node.js 15+) means a Promise rejected but no .catch() handler or try/catch block was attached to handle the failure. In browsers, unhandled rejections may crash the page. In Node.js, they crash the process.
What Causes It
1. Missing .catch() on Fetch Call
// ❌ No error handler
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data));
// If fetch fails — unhandled rejection!
2. Async Function Error Not Caught
// ❌ try/catch missing in async function
async function loadData() {
const response = await fetch('/api/data'); // If this throws...
return response.json();
}
loadData(); // ... this promise rejects with no handler
3. Promise in a Callback
button.addEventListener('click', () => {
fetch('/api/delete', { method: 'DELETE' })
.then(r => r.json());
// No .catch() — rejection goes unhandled
});4. Promise.all with No Catch
Promise.all([
fetch('/api/a'),
fetch('/api/b') // If this fails...
]).then(([a, b]) => console.log(a, b));
// ... Promise.all rejects, and there's no .catch()
How to Fix It
1. Always Add .catch()
The simplest fix — always end promise chains with .catch():
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
console.error('Request failed:', error);
showErrorMessage('Failed to load data');
});2. Wrap Async Functions in try/catch
async function loadData() {
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
console.error('Failed to load:', error);
return null; // Graceful degradation
}
}Anticipating confusion: If you call loadData() and want to handle errors from outside, either return the result and let the caller handle it, or return a fallback value as shown above.
3. Handle Errors in Event Listeners
button.addEventListener('click', async () => {
try {
const response = await fetch('/api/delete', { method: 'DELETE' });
console.log('Deleted:', await response.json());
} catch (error) {
console.error('Delete failed:', error);
}
});4. Add Catch to Promise.all
Promise.all([
fetch('/api/a'),
fetch('/api/b')
])
.then(([a, b]) => console.log(a, b))
.catch(error => {
console.error('One or more requests failed:', error);
});
// Or use Promise.allSettled to handle each result individually
const results = await Promise.allSettled([
fetch('/api/a'),
fetch('/api/b')
]);
results.forEach((r, i) => {
if (r.status === 'rejected') {
console.log(`Request ${i} failed:`, r.reason);
}
});5. Set Up Global Handlers
As a last resort (for errors you missed), set up global handlers:
Browser:
window.addEventListener('unhandledrejection', (event) => {
console.error('Unhandled rejection:', event.reason);
// Log to your error tracking service
event.preventDefault(); // Prevent default error in console
});Node.js:
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// Log and clean up
});Prevention
- Always return promises from functions — so callers can attach
.catch(). - Add
.catch()to every.then()chain — make it a habit. - Use async/await with try/catch — it’s harder to forget than
.catch(). - Enable ESLint’s
no-unhandled-promise-rejectionrule — catches these statically. - Use
Promise.allSettled()instead ofPromise.all()when you need to handle individual failures.
ESLint Configuration
{
"rules": {
"no-unhandled-promise-rejection": "error"
}
}Summary
| Scenario | Fix |
|---|---|
| Promise chain | Add .catch() at the end |
| Async function | Wrap in try/catch |
| Event callback | Use async + try/catch |
| Promise.all | Add .catch() or use Promise.allSettled |
| Global safety net | Add unhandledrejection listener |
Golden rule: Every Promise should either have a .catch() or be inside a try/catch. No exceptions.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro