Async bugs and race conditions in JavaScript
A missing await, results in the wrong order, and updates that overwrite each other under load.
What is async and race condition?
Code that assumes work has finished when it has not. The symptom is a Promise where a value should be, results arriving in an unexpected order, or state that is correct with one user and wrong with several.
Why it happens
An async function always returns a promise, so forgetting a single await hands the promise itself onward. `return somePromise` inside a try block escapes before it can reject, so the catch never runs. And every await is a point where other code can run — if you read a value, await, then write it back, anything that ran in the gap is silently overwritten.
How to recognise it
- "[object Promise]" or typeof 'object' where a value was expected.
- It works with one item and breaks with several.
- Output order changes between runs.
- A try/catch around async work never catches anything.
Errors and symptoms this causes
- [object Promise] in output
- value is undefined after await
- results in wrong order
- try/catch does not catch async error
- UnhandledPromiseRejection
How to fix it
Await everything that returns a promise, and use Promise.all when you need every result rather than the first. Never hold a copy of shared state across an await — read and write without yielding in between. Test concurrency with concurrent input; a sequential test cannot find a race.
Practise async and race conditions
Working code with one bug in it. Find it, fix it in the browser, and see the explanation. No account needed.