Concurrency ⚑ High severity

Missing await — Race Condition

An async call without await returns a pending Promise, causing hard-to-reproduce race conditions in production.

Missing `await` on an async function call doesn’t make the function fail silently — it returns a pending Promise that gets used immediately. The code continues with `undefined` or an incomplete value, creating a race condition that’s incredibly hard to reproduce locally (the debugger’s timing changes everything). This typically surfaces in Express route handlers where async middleware returns before the database call completes.

❌ Vulnerable
// VULNERABLE — missing await
app.get('/user/:id', async (req, res) => {
  const dbQuery = pool.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
  // Missing await! dbQuery is a pending Promise, not the result
  res.json({ user: dbQuery.rows[0] }); // dbQuery.rows is undefined
});
✓ Fixed
// FIXED — await the promise
app.get('/user/:id', async (req, res) => {
  const result = await pool.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
  res.json({ user: result.rows[0] });
});
The Next.js team had a body cloning race where the request body wasn’t awaited before invoking the server action handler — caused hard-to-reproduce failures in production.
PullLight’s analysis looks for async function bodies where a database call, fetch, or file operation is called without `await` — especially in Express route handlers and middleware. The detector flags patterns like `pool.query(...)` assigned to a variable that’s then accessed immediately, and identifies when a Promise object property (`.rows`, `.data`, `.json`) is accessed without first awaiting the parent.
See it in action — paste a diff into /analyze
Try a vulnerable example: pool.query(`SELECT * FROM users WHERE id = ${req.params.id}`)
Analyze a diff →