TypeError: object coroutine cant be used in await expression in AsyncIO
Add parentheses to call the coroutine function: change await fetch_data to await fetch_data().
Root Cause Analysis
This error occurs when Python executes an await expression on an un-called coroutine function reference (await async_function), or conversely attempts to await an object that does not implement the __await__ protocol.
1. Missing Parentheses on Async Function Calls
In Python, an async def my_func(): declaration defines a coroutine function (a function that returns a coroutine object when called). Writing await my_func passes the raw function object to await. Because function objects do not implement __await__, Python raises TypeError: object coroutine can't be used in 'await' expression or TypeError: object function can't be used in 'await' expression.
2. Awaiting Synchronous Helper Functions
Attempting to await a regular def synchronous function that returns a standard primitive (like a string or int) triggers TypeError: object int can't be used in 'await' expression.
3. Double Awaiting a Coroutine Object
Assigning coro = my_func() and calling await coro twice: a coroutine object can only be consumed once.
4. Passing Coroutine Functions into asyncio.gather Without Invoking
Passing asyncio.gather(func1, func2) instead of asyncio.gather(func1(), func2()).
Reproduction Code (MCVE)
import asyncio
async def fetch_user():
return {'id': 1}
async def main():
# Bug: missing parentheses await fetch_user instead of await fetch_user()
await fetch_user
asyncio.run(main())
Solution 1: Invoke Coroutine Function with Parentheses
Add parentheses to execute the function and pass the resulting coroutine object to await.
import asyncio
async def fetch_user():
await asyncio.sleep(0.01)
return {'id': 1, 'name': 'Alice'}
async def main():
# Correct: call the coroutine function
user = await fetch_user()
print(f'User retrieved: {user}')
asyncio.run(main())
Solution 2: Use asyncio.to_thread for Synchronous Blocking Functions
If the function is synchronous and cannot be awaited directly, run it in a thread pool using asyncio.to_thread().
import asyncio
import time
def sync_blocking_task(n):
time.sleep(0.01)
return n * 2
async def main():
# Safely execute synchronous functions in async pipelines
result = await asyncio.to_thread(sync_blocking_task, 21)
print(f'Thread result: {result}')
asyncio.run(main())
A common mistake is forgetting await entirely on an async call (e.g. user = fetch_user()). This returns an un-awaited <coroutine object> and causes Python to emit RuntimeWarning: coroutine 'fetch_user' was never awaited. Always pair async function calls with await. Edge cases occur with class methods: ensure @classmethod or @staticmethod decorators precede async def. Contrast this error with TypeError: 'coroutine' object is not subscriptable, which occurs when doing fetch_user()['id'] without await.