A Promise represents the eventual result of an asynchronous operation. When a Promise is created but neither awaited, returned, nor given a rejection handler, it is said to be "floating": nothing in the code observes whether it eventually resolves or rejects.
This is a frequent source of bugs:
map() call, is just as easy to leave unhandled as a single Promise, and is a common
way to accidentally launch several operations without ever finding out if any of them failed.This rule applies to Promise-valued statements. Promises used where another type is expected, such as in a conditional or a spread, are covered by {rule:javascript:S6544}.
An unhandled rejection is not contained to the operation that failed. Since Node.js 15, the default --unhandled-rejections mode is throw, which
raises the rejection as an uncaught exception and terminates the process unless an unhandledRejection hook is registered. A single
unobserved background task can therefore take down a server that was otherwise healthy.
Make sure every Promise-returning statement is handled in one of the following ways:
await it.return it, so that the caller becomes responsible for handling it..catch(), or pass a rejection handler as the second argument to .then().Promise.all(), Promise.allSettled(),
Promise.race(), or Promise.any() before handling the result, instead of leaving an array of Promises unhandled.If a Promise’s outcome genuinely does not matter and you want to make that explicit, use the void operator on the expression. This
documents that the Promise is intentionally left unobserved. Note that this does not make rejections disappear: it only silences this rule, so it
should be reserved for Promises that you know cannot practically reject, or that are otherwise covered by a global unhandled-rejection handler.
function sendMetrics(payload) {
fetch('/metrics', { method: 'POST', body: payload }); // Noncompliant: nothing handles a failed request
}
async function sendMetrics(payload) {
await fetch('/metrics', { method: 'POST', body: payload });
}
function logAndForget() {
fetchLogs().then(logs => storeLogs(logs)); // Noncompliant: no rejection handler
}
function logAndForget() {
fetchLogs()
.then(logs => storeLogs(logs))
.catch(error => reportError(error));
}
function notifyAll(subscribers) {
subscribers.map(subscriber => subscriber.notify()); // Noncompliant: an array of unhandled Promises
}
async function notifyAll(subscribers) {
await Promise.all(subscribers.map(subscriber => subscriber.notify()));
}
function onClick() {
trackEvent('button_clicked'); // Noncompliant: the Promise is left unhandled and is not marked as intentionally ignored
}
function onClick() {
// The analytics call is not expected to fail in a way that matters here.
void trackEvent('button_clicked');
}
void operator