DoesItHold

The missing await bug in JavaScript async functions

In an async function, calling a function that returns a Promise gives you the Promise, not its resolved value. Forget await and the next line reads a pending Promise as if the data were already there.

The quick answer

Add await before the call that returns a Promise. Without it, the returned value is a Promise object, so reading a property or calling a method on the expected data does not behave as you intend.

A minimal example

Bugged: the response is a Promise, not the fetch result
async function showUser() {
  const user = getUser();
  console.log(user.name);
}
Fixed: await resolves the Promise first
async function showUser() {
  const user = await getUser();
  console.log(user.name);
}

In the bugged version, response is a Promise, so calling json on it is not reading the parsed body. Adding await makes response the resolved value before the next line runs.

How to debug it

  1. Find every call that returns a Promise: fetch, database drivers, and most I/O.
  2. Check whether the returned value is used directly on the next line.
  3. Follow the value: if a Promise is treated like plain data, an await is missing.
  4. Add await, or return the Promise so the caller can await it.

Common wrong fixes

  • Wrapping the call in another Promise instead of awaiting the one you already have.
  • Adding .then in one place but leaving the value used synchronously right after.
  • Marking the function async without ever awaiting the Promise inside it.

Limits of this guide

This covers the single-missing-await case. Real async bugs also include unhandled rejections, races between concurrent awaits, and ordering across event loops. The challenge focuses on the ordering mistake shown here.

Authoritative references

  1. ECMAScript language specification — Await
  2. MDN — async function
  3. MDN — await operator

Ready to try it?

Fix this bug in a free challenge

Related pages