Why is this an issue?

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:

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}.

What is the potential impact?

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.

How to fix it

Make sure every Promise-returning statement is handled in one of the following ways:

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.

Code examples

Noncompliant code example

function sendMetrics(payload) {
  fetch('/metrics', { method: 'POST', body: payload }); // Noncompliant: nothing handles a failed request
}

Compliant solution

async function sendMetrics(payload) {
  await fetch('/metrics', { method: 'POST', body: payload });
}

Noncompliant code example

function logAndForget() {
  fetchLogs().then(logs => storeLogs(logs)); // Noncompliant: no rejection handler
}

Compliant solution

function logAndForget() {
  fetchLogs()
    .then(logs => storeLogs(logs))
    .catch(error => reportError(error));
}

Noncompliant code example

function notifyAll(subscribers) {
  subscribers.map(subscriber => subscriber.notify()); // Noncompliant: an array of unhandled Promises
}

Compliant solution

async function notifyAll(subscribers) {
  await Promise.all(subscribers.map(subscriber => subscriber.notify()));
}

Noncompliant code example

function onClick() {
  trackEvent('button_clicked'); // Noncompliant: the Promise is left unhandled and is not marked as intentionally ignored
}

Compliant solution

function onClick() {
  // The analytics call is not expected to fail in a way that matters here.
  void trackEvent('button_clicked');
}

Resources

Documentation

Related rules