Skip to content

In some obscure cases, StopIteration exceptions can be turned into RuntimeErrors when passing through nurseries #229

Closed

Description

@njsmith

There are some very obscure edge cases where using async generators does the wrong thing. For example, this code

import trio

async def fail():
    raise ValueError

async def main():
    async with trio.open_nursery() as nursery:
        nursery.spawn(fail)
        raise StopIteration

trio.run(main)

Ought to raise a MultiError([StopIteration(), ValueError()]), but instead it raises a MultiError([RuntimeError(), ValueError()]). This is because you can't throw a StopIteration into an async_generator-based async generator (for details see here) – it gets wrapped into a RuntimeError. If we let that RuntimeError propagate, then acontextmanager could turn it back, but here it gets wrapped into a MultiError instead so the magic doesn't work.

I guess we could make acontextmanager smart enough to look inside MultiErrors? Or stop using acontextmanager and write this context manager directly? Or just not worry about it until we can drop 3.5 support and switch to using native async generators, which don't have this problem? It's very unusual to have free-floating StopIteration exceptions wandering around like this, and that's the only case that's affected. But I figured we should record the problem in any case.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions