python/cpython · error · RuntimeError
cannot notify on un-acquired lock
Error message
cannot notify on un-acquired lock
What it means
asyncio.Condition.notify()/notify_all() raise RuntimeError when the calling task does not hold the condition's lock. The docstring in-source notes awakened tasks only resume after reacquiring the lock, so notifying without ownership would break the wakeup protocol.
Source
Thrown at Lib/asyncio/locks.py:327
while not result:
await self.wait()
result = predicate()
return result
def notify(self, n=1):
"""By default, wake up one task waiting on this condition, if any.
If the calling task has not acquired the lock when this method
is called, a RuntimeError is raised.
This method wakes up n of the tasks waiting for the condition
variable; if fewer than n are waiting, they are all awoken.
Note: an awakened task does not actually return from its
wait() call until it can reacquire the lock. Since notify() does
not release the lock, its caller should.
"""
if not self.locked():
raise RuntimeError('cannot notify on un-acquired lock')
self._notify(n)
def _notify(self, n):
idx = 0
for fut in self._waiters:
if idx >= n:
break
if not fut.done():
idx += 1
fut.set_result(False)
def notify_all(self):
"""Wake up all tasks waiting on this condition. This method acts
like notify(), but wakes up all waiting tasks instead of one. If the
calling task has not acquired the lock when this method is called,
a RuntimeError is raised.
"""View on GitHub (pinned to bc6749cc3b)
Solutions
- Structure producers as: async with cond: ...; cond.notify_all()
- Ensure the notifying task is the one holding the lock (acquire it first)
- Consider asyncio.Event or Queue when lock ownership is hard to guarantee
Example fix
# before
async def producer(item):
queue.append(item)
cond.notify_all() # RuntimeError
# after
async def producer(item):
async with cond:
queue.append(item)
cond.notify_all() Defensive patterns
Strategy: validation
Validate before calling
if not cond.locked():
# notify() would raise; wrap in 'async with cond' first Prevention
- Notify only inside the async-with block that holds the lock
- Have the same task that holds the lock do the notify
- Consider asyncio.Event/Queue when ownership is awkward
When it happens
Trigger: cond.notify() outside 'async with cond'; notify after the async-with body completed; producer task notifying a condition whose lock a consumer still holds.
Common situations: Porting threading code where notify is called loosely; splitting produce/consume across tasks without sharing the async with block; early returns that skip the context manager but still notify in cleanup.
Related errors
- cannot wait on un-acquired lock
- Lock is not acquired.
- BoundedSemaphore released too many times
- {self!r} is bound to a different event loop
- Failed to fetch glossary.json
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/1b7ae5c7fd22d314.
Report an issue: GitHub.