Hi blackdrag*,

would something like the following work, assuming an exception inside the async block would be wrapped in an AsyncWrapperException by Groovy:

for await (value in channel) try {
     println value
}
catch(AsyncWrapperException ae) {
    ...
}
catch(Throwable t) {
    ...
}

Cheers,
mg

*Too many Jochens right now ;-)


Am 28.10.2026 um 21:14 schrieb Jochen Theodorou via dev:
On 10/28/26 17:11, Daniel Sun wrote:
Hi Jochen, Matt,

Thanks for the example and the follow-up.

`defer` for `channel.close()` is still the right cleanup tool, and keeping the `Awaitable` from `async` so you can `await` it after the `for await` loop remains the cleanest way I see to surface the producer exception without inventing `async { } finally { }`.


my example was:

```groovy
def channel = AsyncChannel.create(2)

// send data to channel in another thread
async {
     for (int i = 1; i <= 3; i++) {
         someCall()
         channel.send(i * i)
     }
     channel.close()
}

// print all values send till the channel closed
for await (value in channel) {
     println value
}
```

and the problem was that if someCall() throws an exception we are left hanging. Yes, if we do not do a free async block this cannot happen, but then... why do we then allow them at all? Because it makes for short code.

The "Dungeon waves" example on https://groovy.apache.org/blog/groovy-async-await for example has the same basic problem. a free async, that will not be able to transport its exception.

I really think we need to find a solution to this.

bye Jochen

Reply via email to