# Asyncio timeout on event wait

**URL:** <https://discuss.python.org/t/asyncio-timeout-on-event-wait/106002>\
**Category:** Python Help\
**Created:** [February 4, 2026, 9:41am UTC](https://discuss.python.org/t/asyncio-timeout-on-event-wait/106002 "2026-02-04T09:41:54Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![xitop](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/xitop/32/13242_2.png) [@xitop](https://discuss.python.org/u/xitop)\
**Post date:** [February 4, 2026, 9:41am UTC](https://discuss.python.org/t/asyncio-timeout-on-event-wait/106002/1 "2026-02-04T09:41:54Z")

</div>

I had code like this:

```python
    try:
        async with asyncio.timeout(delay):
            await event.wait()
    except TimeoutError:
        return "No event"
    return "Event!"

```

Unfortunately, it is not _either_ timeout _or_ event as I originally assumed. When the event and the timeout occur almost in the same time, we could have both the timeout and the event. The code below proved it. But as I said, it is timing sensitive.

```python
    try:
        async with asyncio.timeout(delay):
            await event.wait()
    except TimeoutError:
        assert not event.is_set() # <-- not always true!
        return "No event"
   ...

```

An `await` cannot both succeed and fail. It looks to me like other tasks can be run during timeout handling in the `timeout` context manager. I don’t know, I just cannot explain the event state change otherwise.

Anyway, in my case it introduced an ugly bug. This is how I corrected it:

```python
    try:
        async with asyncio.timeout(delay):
            await event.wait()
    except TimeoutError:
        pass
    return "Event!" if event.is_set() else "No event"

```

I decided to post this because I would like to know if it can be considered a “gotcha” that should be somehow addressed, e.g. by enhancing the doumentation?

---

<div class="post-metadata">

**Author:** ![tapetersen](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/tapetersen/32/28049_2.png) [@tapetersen](https://discuss.python.org/u/tapetersen)\
**Post date:** [February 4, 2026, 12:04pm UTC](https://discuss.python.org/t/asyncio-timeout-on-event-wait/106002/2 "2026-02-04T12:04:56Z")

</div>

While there is indeed nothing preventing the event to be set after you’ve awaited it that shouldn’t be possible without some await between the wait and the check.

Is there an await in the real code?

Because otherwise it should only really be possible if the event is set by another thread which is not supported as Event like most asyncio structures are not thread safe.

---

<div class="post-metadata">

**Author:** ![tapetersen](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/tapetersen/32/28049_2.png) [@tapetersen](https://discuss.python.org/u/tapetersen)\
**Post date:** [February 4, 2026, 12:07pm UTC](https://discuss.python.org/t/asyncio-timeout-on-event-wait/106002/3 "2026-02-04T12:07:59Z")

</div>

Or maybe (I would have to check the code) it could be that we hit the TimeoutError even when the event is set if it had already expired when we first called `wait`

Edit:

Just checked and if the event is set when `wait` is called it doesn’t yield to the event loop and so as your examples above are written you really should’ve be able to get a `TimeoutError` unless you’re calling `set()` on the event from another thread which is a bug (use [call\_soon\_threadsafe](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_soon_threadsafe) instead)

---

<div class="post-metadata">

**Author:** ![xitop](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/xitop/32/13242_2.png) [@xitop](https://discuss.python.org/u/xitop)\
**Post date:** [February 4, 2026, 1:27pm UTC](https://discuss.python.org/t/asyncio-timeout-on-event-wait/106002/4 "2026-02-04T13:27:38Z")

</div>

- I corrected a typo, there is `async with`, not just `with` as I wrote by mistake.
- there is no other `await`
- there are no other threads

Please find attached a reproducer. It stops with an assertion error on my PC and Python 3.11, 3.12, 3.13 and 3.14.

```python
import asyncio

ev = asyncio.Event()

async def ev_wait(delay):
    try:
        async with asyncio.timeout(delay):
            await ev.wait()
    except TimeoutError:
        assert not ev.is_set(), "Bang!"

async def ev_send(delay):
    await asyncio.sleep(delay)
    ev.set()

async def main():
    for delta in range(-100, 100):
        ev.clear()
        t1 = asyncio.create_task(ev_wait(0.01))
        t2 = asyncio.create_task(ev_send(0.01 + delta/10000))
        await t1
        await t2

if __name__ == " __main__":
    asyncio.run(main())

```
