A missing await is a control-flow bug
When an async function is called without await, the next line receives a Promise—not the eventual value.
DoesItHold Editorial · · reviewed · guide-js-await-001
Direct answer
Add await at the boundary where the resolved value is required, and ensure the containing function is async.
An async function always returns a Promise. Without await, property access, arithmetic or branching happens against that Promise object instead of its resolved value. The failure may be immediate, such as reading an undefined property, or delayed until a value reaches a different layer.
Treat the defect as a sequencing problem. The useful question is not ‘where can I add await?’ but ‘which operation first requires the settled value?’ Keeping that boundary narrow preserves concurrency for independent work and makes the dependency visible.
- 01CallfetchUser() returns Promise<User>
- 02Boundaryname is needed synchronously
- 03Suspendawait yields this continuation
- 04Resumeuser is now the resolved User
Minimal example
Scrollable code region
async function loadName() {
const user = fetchUser();
return user.name;
}async function loadName() {
const user = await fetchUser();
return user.name;
}What changes: The corrected version reads name only after user is a resolved value; the buggy version reads it from Promise<User>.
Debugging method
Inspect the runtime value, follow the Promise to its first synchronous consumer and place await at the narrowest boundary that needs the result.
- Log or inspect the value and confirm whether it is a Promise before changing code.
- Find the first property read, comparison or calculation that needs the resolved value.
- Make the containing function async, add await there and keep independent Promises concurrent.
- Exercise both the success and rejection paths so the fix does not swallow an error.
Common wrong fix
Adding a timeout, optional chaining or a second Promise wrapper hides the symptom; none restores the required sequencing. Adding await to every expression can also serialize work that was independent.
Limits and edge cases
Top-level await is restricted by the script or module environment, and awaiting inside loops can unintentionally serialize requests. When operations are independent, start them together and await a combinator such as Promise.all at the point their results are needed.