Asyncerrorrecommended presetstrict preset✓ autofix supported

ai-guard/no-floating-promise

Catches unawaited promises and fire-and-forget calls that silently swallow errors

What it does

Flags async function calls that are not `await`ed and have no `.catch()` handler attached — known as "floating promises." The call is made, but its result (including any rejection) is silently discarded.

Why AI tools generate this pattern

When an async function rejects and nothing is listening, Node.js silently ignores it. There is no error in the console, no stack trace, no crash — the failure simply disappears. This is one of the most common patterns in AI-generated backend code because AI models learn from examples that often show only the "happy path." The `await` is omitted, the promise floats, and the bug only surfaces in production when data is missing or a user action silently fails.

Code Examples

Incorrect (Flagged by AI Guard)
// No await — if sendEmail rejects, the error is silently lost
function createUser(data: UserData) {
  sendWelcomeEmail(data.email); // ← floating promise
  return db.users.create(data);
}

// Common AI pattern: calling async functions inside callbacks
router.post('/order', (req, res) => {
  processPayment(req.body); // ← floating promise — payment may fail silently
  res.json({ status: 'ok' });
});
Correct (Safe & Deterministic)
// Await the async call
async function createUser(data: UserData) {
  await sendWelcomeEmail(data.email);
  return db.users.create(data);
}

// Or handle errors explicitly using .catch()
router.post('/order', (req, res) => {
  processPayment(req.body)
    .then(() => res.json({ status: 'ok' }))
    .catch((err) => {
      console.error('Payment failed:', err);
      res.status(500).json({ error: 'Payment processing failed' });
    });
});

Safe Autofix

This rule supports a safe autofix that marks floating promise calls as explicit fire-and-forget by prefixing with `void`.

Before fix:

sendEmail(user.email);

After fix:

void sendEmail(user.email);

How to Fix

  1. Add `await` before the async call (requires the parent function to be `async`)
  2. Attach `.catch((err) => ...)` to handle the rejection explicitly
  3. Store the promise in a variable and handle it before the function returns
  4. If fire-and-forget is intentional, make it explicit with `void` (this is what autofix applies)

Nuances & False Positive Prevention

Legitimate usage can be exempted with inline disable comments (// ai-guard-disable-next-line no-floating-promise) when appropriate.

Configuration

Enable or override this rule in your ESLint configuration:

eslint.config.mjs
// eslint.config.mjs
rules: {
  'ai-guard/no-floating-promise': 'error',
}

Related Rules