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