Rethinking Exceptions in the Context of Loom and Structured Concurrency

Attila Kelemen attila.kelemen85 at gmail.com
Fri Dec 19 19:31:21 UTC 2025


I don't think STS is really a special case. The same issue happens in many
other places, so - to me - it would feel very out of place that Loom itself
has a different error handling mechanism. That is, there is no clearly good
solution, because as Alex alluded to it on this thread: If exceptions or
error values are better depends on the specific context, not technical
details, if the code is parallel or not. Given my experience, most of the
time you do prefer exceptions over error values. Though I would love to see
a feature in Java, where a function could return an error value, and if it
is not handled, then it is automatically turned into an exception.

Anyway, let me go through the problems on this small sample code:

```
String run() {
  try (var scope = StructuredTaskScope.open()) {
    var results = new ArrayList<StructuredTaskScope.Subtask<?>>();
    results.add(scope.fork(() -> 42));
    results.add(scope.fork(() -> {
      throw new RuntimeException("Oh, no!");
    }));

    try {
      scope.join();
    } catch (InterruptedException e) {
      // I guess cancelled?
      throw new RuntimeException(e);
    } catch (StructuredTaskScope.FailedException e) {
      // ok, we will check.
    }

    return results.stream()
        .map(result -> switch (result.state()) {
          case SUCCESS -> "Success: " + result.get();
          case FAILED -> "Error: " + result.exception().getMessage();
          case UNAVAILABLE -> throw new AssertionError("But why?");
        })
        .collect(Collectors.joining(", "));
  }
}
```

1. `InterruptedException`: I do think that thread interrupts are a poor way
to manage cancellation. The fact that they are checked is a nightmare,
because effectively almost all APIs should prepare for the fact that
whatever they do might do something longer, and must be cancelled which
would imply that all methods should declare `InterruptedException` (which
is of course absurd). Even if STS doesn't pick up the job to bring sane
cancellation into the JDK, it should wrap cancellation into a new unchecked
exception like `OperationCancelledException` (or something like that). This
would not be important, because if later Java decides to introduce better
cancellation, then a checked exception will be practically impossible to
remove from an API, while an unchecked one could be retrofitted to extend a
new one.

2. `StructuredTaskScope.FailedException`: It might look a bit uglier than
if `join` returned a boolean or something, but consider the consequence: In
many cases people don't want to handle the exception, and just treat it as
a (semi-)catastrophic failure, and let some generic loop retry somewhere.
Now, if you made it a return value, then suddenly you made things more
awkward for the common case for minor gain. Because the main issue with
exceptions compared to error values is that the `try-catch` creates a
scope, but it is not really an issue here.

3. `State.UNAVAILABLE`: Maybe a bit off-topic, but let me put it here: It
is kinda evil in my opinion, because most of the time I would fetch the
result after a `join` where that is an impossibility, yet its presence
makes switch expressions awkward. It would be nice to have a `ResultState`
with only two states `SUCCESS` or `FAILED`. Then of course, the old `State`
is not necessary, because it could become just a `boolean isAvailable()`
instead.

Anyway, if the main issue was that `join` throws an exception on failure
rather than signals it through a return value (or similar), then I'm
strongly against the return value, because it is not really STS relevant to
deliver such a paradigm shift to the JDK, and I would not want STS delivery
to be delayed just because of the requirement of introducing a new paradigm
which is not directly relevant to STS.

Attila

Eric Kolotyluk <eric at kolotyluk.net> ezt írta (időpont: 2025. dec. 19., P,
5:56):

> Hi all,
>
> I’m starting a new thread to continue a discussion that emerged elsewhere,
> per mailing list etiquette, and to give the topic a clean and traceable
> home.
>
> My interest here isn’t reactive to any one exchange. I’ve been
> experimenting with Loom since its early iterations, and over time it has
> sharpened a concern I already had: whether Java’s traditional exception
> model remains the right default abstraction in a world of structured
> concurrency, virtual threads, and large-scale composition.
>
> To be clear, this is not a claim that “exceptions are broken” or that Java
> should abandon them. Java’s exception system has supported billions of
> lines of successful code, and I’ve used it productively for decades.
> Rather, Loom makes certain trade-offs more visible — particularly around
> control flow, cancellation, failure propagation, and reasoning about
> lifetimes — that were easier to ignore in a purely thread-per-task world.
>
> The core questions I’m interested in exploring are along these lines:
>
>    - How do unchecked exceptions interact with structured concurrency’s
>    goal of making lifetimes and failure scopes explicit?
>    - Do exceptions remain the best abstraction for expected failure in
>    highly concurrent, compositional code?
>    - Are there patterns (or emerging idioms) that Loom encourages which
>    mitigate long-standing concerns with exceptions — or does Loom expose new
>    ones?
>    - More broadly, should Java be thinking in terms of additional
>    failure-handling tools rather than a single dominant model?
>
> I’m not advocating a specific alternative here — just inviting a technical
> discussion about whether Loom changes how we should think about error
> handling, and if so, how.
>
> That said, exposure to other ecosystems (e.g., Scala, Kotlin, and more
> recently Rust) has broadened how I think about failure modeling. One thing
> I’ve consistently appreciated about Java is that it tends to integrate
> external ideas deliberately, rather than reflexively rejecting them or
> adopting them wholesale. Loom itself is a good example of that approach.
>
> I’m interested in whether error handling deserves a similar re-examination
> in light of Loom’s goals.
>
> Looking forward to the discussion.
>
> Cheers,
> Eric
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20251219/edf62527/attachment.htm>


More information about the loom-dev mailing list