In Python and JavaScript, calling an async function without await doesn't raise an error. The function returns a Promise (or coroutine) that silently goes unresolved. The operation you expected to happen — the database write, the API call, the file save — never executes.
Why this is so common
When AI generates code, it often converts synchronous functions to async as part of a larger refactor. It adds async to the function definition and updates most call sites. But "most" isn't "all." One missing await buried in an error handler or a cleanup function goes unnoticed because the happy path still works.
In JavaScript, the problem is worse: calling an async function without await returns a Promise object that is truthy. So if (saveToDatabase(data)) evaluates to true even though nothing was saved.
Real-world impact
We've seen this cause:
- Audit logs that silently stop recording - Payment webhooks that acknowledge but never process - Background jobs that appear to complete but skip critical steps - Error reporters that fail to report their own errors
The pattern is always the same: the system looks healthy because the async call doesn't throw — it just doesn't do anything.
What ASYNC001 catches
ASYNC001 identifies every call to an async function that isn't preceded by await, yield from, or otherwise consumed. It works across Python and JavaScript/TypeScript, understands method chains, and handles the common patterns where a missing await causes silent failures.
This is one of our most frequently triggered checks — and one where developers almost always say "oh, that would have been bad."
ASYNC001 is available with a StableStack license.
pip install stablestack