no-unhandled-promise
ESLint rule documentation for no-unhandled-promise
๐ก Live from GitHub โ This documentation is fetched directly from no-unhandled-promise.md and cached for 6 hours.
Keywords: unhandled promise, promise rejection, async error handling, Promise, async/await, error handling, Node.js, JavaScript promises, async patterns, promise chains, try/catch, await, error propagation, CWE-1024, SonarQube RSPEC-4635
Disallow unhandled Promise rejections with LLM-optimized suggestions for proper async error handling
Disallow unhandled Promise rejections with LLM-optimized suggestions for proper async error handling. This rule detects promises that are created but never have their rejection handled, preventing silent failures in production applications.
Quick Summary
| Aspect | Details |
|---|---|
| Severity | Error (production safety) |
| Auto-Fix | โ No (complex logic) |
| Category | Quality |
| ESLint MCP | โ Optimized for ESLint MCP integration |
| Best For | Production applications, async codebases |
| Suggestions | โ Add .catch(), use try/catch, use await |
Rule Details
Why This Matters
| Issue | Impact | Solution |
|---|---|---|
| ๐ Silent Failures | Errors swallowed without logging | Proper error handling |
| ๐ Debugging | Hard to trace async failures | Centralized error handling |
| โก Reliability | Application crashes unexpectedly | Graceful error recovery |
| ๐ Monitoring | No visibility into promise failures | Error tracking & alerting |
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
ignoreInTests | boolean | true | Skip promise checks in test files |
ignoreVoidExpressions | boolean | false | Skip promises in void expressions |
Examples
โ Incorrect
// Unhandled promise rejection
fetchUserData(userId);
// Promise chain without error handling
apiCall().then(processData).then(saveToDatabase);
// Async function without await or error handling
async function processOrder(orderId) {
validateOrder(orderId); // Promise not handled
return orderId;
}โ Correct
// Handle with .catch()
fetchUserData(userId).catch((error) => {
logger.error('Failed to fetch user data', { userId, error });
});
// Complete promise chain
apiCall()
.then(processData)
.then(saveToDatabase)
.catch((error) => {
logger.error('API pipeline failed', { error });
});
// Use try/catch in async functions
async function processOrder(orderId) {
try {
await validateOrder(orderId);
return orderId;
} catch (error) {
logger.error('Order validation failed', { orderId, error });
throw error;
}
}
// Or use await at the call site
async function handleOrder(orderId) {
await processOrder(orderId); // Error will propagate
}Configuration Examples
Basic Usage
// eslint.config.mjs
export default [
{
rules: {
'maintainability/no-unhandled-promise': 'error',
},
},
];Ignore Test Files
{
rules: {
'maintainability/no-unhandled-promise': ['error', {
ignoreInTests: true // Default: true
}]
}
}Strict Mode (No Exceptions)
{
rules: {
'maintainability/no-unhandled-promise': ['error', {
ignoreInTests: false,
ignoreVoidExpressions: false
}]
}
}LLM-Optimized Output
๐จ CWE-1024 | Unhandled promise rejection detected | HIGH
Fix: Add .catch() handler or use try/catch | https://rules.sonarsource.com/javascript/RSPEC-4635/
Suggestions:
๐ง Add .catch(error => { ... })
๐ Use try/catch block
โก Use await in async functionAdvanced Usage
Integration with Error Boundaries
// React component with error boundary
class ErrorBoundary extends React.Component {
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
// Handle async errors from promises
logger.error('React error boundary caught error', {
error: error.message,
componentStack: errorInfo.componentStack
});
}
}
// Usage
<ErrorBoundary>
<AsyncComponent />
</ErrorBoundary>Global Unhandled Rejection Handler
// Global handler for truly unhandled rejections
process.on('unhandledRejection', (reason, promise) => {
logger.error('Unhandled promise rejection', {
reason,
promise: promise.toString(),
});
// Don't exit process in production
});When Not To Use
| Scenario | Recommendation |
|---|---|
| ๐งช Prototyping | Disable or use warning level |
| ๐ Tutorials | Add to ignorePatterns |
| ๐ง Build Scripts | Use ignorePatterns: ['scripts'] |
Comparison with Alternatives
| Feature | no-unhandled-promise | eslint-plugin-promise | ESLint built-in |
|---|---|---|---|
| Promise Detection | โ Static analysis | โ Runtime checks | โ No |
| Auto-Fix | โ No | โ No | โ No |
| LLM-Optimized | โ Yes | โ No | โ No |
| Customizable | โ Yes | โ ๏ธ Limited | โ No |
Error Message Format
๐จ CWE-1024 | Unhandled promise rejection detected | HIGH
Fix: Add .catch() handler or use try/catch | https://rules.sonarsource.com/javascript/RSPEC-4635/Related Rules
no-silent-errors- Detects empty catch blocksno-missing-error-context- Requires error context information
Further Reading
- Promise Error Handling - MDN Promise error handling guide
- Async/Await Best Practices - MDN async/await guide
- Node.js Error Handling - Node.js error handling documentation
Known False Negatives
The following patterns are not detected due to static analysis limitations:
Dynamic Variable References
Why: Static analysis cannot trace values stored in variables or passed through function parameters.
// โ NOT DETECTED - Value from variable
const value = externalSource();
processValue(value); // Variable origin not trackedMitigation: Implement runtime validation and review code manually. Consider using TypeScript branded types for validated inputs.
Wrapped or Aliased Functions
Why: Custom wrapper functions or aliased methods are not recognized by the rule.
// โ NOT DETECTED - Custom wrapper
function myWrapper(data) {
return internalApi(data); // Wrapper not analyzed
}
myWrapper(unsafeInput);Mitigation: Apply this rule's principles to wrapper function implementations. Avoid aliasing security-sensitive functions.
Imported Values
Why: When values come from imports, the rule cannot analyze their origin or construction.
// โ NOT DETECTED - Value from import
import { getValue } from './helpers';
processValue(getValue()); // Cross-file not trackedMitigation: Ensure imported values follow the same constraints. Use TypeScript for type safety.