<div dir="auto">Hello <span class="gmail_chip gmail_plusreply" dir="auto"><a href="mailto:eric@kolotyluk.net" style="color:#15c;text-decoration:underline">@Eric Kolotyluk</a></span>,<div dir="auto"><br></div><div dir="auto">Let me start off by giving context -- the way STS uses exceptions is a little more complicated than just "throw, even on very much expected errors".</div><div dir="auto"><br></div><div dir="auto">One of the downsides of STS is that it is the hotelier to several different guests with very different (almost orthogonal) semantic needs -- thus forcing the final design to sardine them together in some uncomfortable ways.</div><div dir="auto"><br></div><div dir="auto">You mentioned one of these pain points in the previous thread -- about the joiner returning null when successful, and exception otherwise.</div><div dir="auto"><br></div><div dir="auto">Stuff like that is usually an indicator that an API is trying to do 2 or more things at once, and can't easily accomodate both in the cleanest way. The literal reason java.lang.Void was created back when was to bandaid this exact problem.</div><div dir="auto"><br></div><div dir="auto">So, understanding that STS is trying to cover multiple different API needs in one hood, hopefully that makes more sense why the answer is null vs exception for that particular joiner. It's not clean, but it serves the purpose well enough, imo.</div><div dir="auto"><br></div><div dir="auto">With that context out of the way, let me respond to your points.</div><div dir="auto"><ul><li>How do unchecked exceptions interact with structured concurrency’s goal of making lifetimes and failure scopes explicit?</li></ul></div><div dir="auto">I'm not sure I follow. Are you asking how unchecked exceptions thrown by MY CLIENT CODE interact with STS? If so, I'd say, the same as everywhere else.</div><div dir="auto"><br></div><div dir="auto">My understanding is that Unchecked is for programming bugs, and therefore, should not be dealt with. The only difference between other contexts and STS is that, for some of the joiners (awaitAll), STS gives you the choice to do that or not. It's not necessarily the default to propagate, which some developers have raised disagreement with in the past.</div><div dir="auto"><ul><li>Do exceptions remain the best abstraction for expected failure in highly concurrent, compositional code?</li></ul><div dir="auto">Well, again, it depends what you mean here. This question and the one before it are rather open-ended.</div><div dir="auto"><br></div><div dir="auto">Currently, the join method throws several different exceptions.</div><div dir="auto"><br></div><div dir="auto">WrongThreadException -- I think using an (unchecked) exception is the right choice here because this situation can only occur via programming error.</div><div dir="auto"><br></div><div dir="auto">IllegalStateException -- Same logic as above.</div><div dir="auto"><br></div><div dir="auto">FailedException -- Some feel this should be replaced by a return type in the vein of Result<T> or something related. I don't necessarily agree, as I still do want a stack trace with line numbers. And if that Result<T> is actually Result<T,Ex> where Ex is an exception, well I think Exceptions are the better vehicle for that type of response instead of Result.</div><div dir="auto"><br></div><div dir="auto">TimeoutException -- This is a great example of what I mean when I say sardine. Normally, this would obviously be a checked exception (an expected failure that no amount of prep time can realistically prevent), but since I can turn off timeouts, forcing everyone to pay for this doesn't make sense. Aka, sardines. But really, the original sin is that code that doesn't do timeouts shouldn't be able to throw this. Sadly, the only real way to do this in Java 25 is by significantly bloating the Java api. You'd have to break apart and duplicate the API in ways that increase the surface area while adding very little semantic meaning. That's a double whammy in the worst way. That'd be like Stream vs IntStream vs DoubleStream all over again. I can definitely understand ehy they do not want that for STS. Maybe some exploration is being done towards remedying this, idk.</div><div dir="auto"><br></div><div dir="auto">InterruptedException -- Well, this one is fine. However you feel about Interrupts and how Java implements them, STS is advertised to handle and emit interrupts "properly", therefore the behaviour here is unavoidable, according to the spec. You'd have to trandform STS into something wildly different in order to change how or if we deal in InterruptedExceptions.</div><div dir="auto"><br></div><div dir="auto">So, from what I can see here, each of the exceptions seem reasonable. Albeit, some are the result of conflicting concerns. But I don't see how any other solution would address these better.</div><ul><li>Are there patterns (or emerging idioms) that Loom encourages which mitigate long-standing concerns with exceptions — or does Loom expose new ones?</li><li>More broadly, should Java be thinking in terms of additional failure-handling tools rather than a single dominant model?</li></ul><div dir="auto">I think Java already has, but even in light of that exploration, chose to use exceptions here.</div><div dir="auto"><br></div><div dir="auto">But frankly, both of these points are broad. I think you need to be more specific here.</div><div dir="auto"><br></div><div dir="auto">I will say, your original post in the previous thread was asking a very different question than this thread. Did you mean to, or are you building up to that?</div></div><br><br><div class="gmail_quote gmail_quote_container" dir="auto"><div dir="ltr" class="gmail_attr">On Fri, Dec 19, 2025, 8:25 AM David Alayachew <<a href="mailto:davidalayachew@gmail.com">davidalayachew@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto">And just for context for all, here is the previous thread where this discussion originated.<div dir="auto"><br></div><div dir="auto"><a href="https://mail.openjdk.org/pipermail/loom-dev/2025-December/008117.html" rel="noreferrer noreferrer" target="_blank">https://mail.openjdk.org/pipermail/loom-dev/2025-December/008117.html</a></div><div dir="auto"><br></div><div dir="auto">You can start reading from there. A few more replies later, and then this new thread was created, so as not to distract from the other topic.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Dec 19, 2025, 1:35 AM Eric Kolotyluk <<a href="mailto:eric@kolotyluk.net" rel="noreferrer noreferrer" target="_blank">eric@kolotyluk.net</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><u></u>

  

    
  
  <div>
    Hi all,<br>
    <br>
    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.<br>
    <br>
    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.<br>
    <br>
    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.<br>
    <br>
    The core questions I’m interested in exploring are along these
    lines:<br>
    <ul>
      <li>How do unchecked exceptions interact with structured
        concurrency’s goal of making lifetimes and failure scopes
        explicit?</li>
      <li>Do exceptions remain the best abstraction for expected failure
        in highly concurrent, compositional code?</li>
      <li>Are there patterns (or emerging idioms) that Loom encourages
        which mitigate long-standing concerns with exceptions — or does
        Loom expose new ones?</li>
      <li>More broadly, should Java be thinking in terms of additional
        failure-handling tools rather than a single dominant model?</li>
    </ul>
    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.<br>
    <br>
    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.<br>
    <br>
    I’m interested in whether error handling deserves a similar
    re-examination in light of Loom’s goals.<br>
    <br>
    Looking forward to the discussion.<br>
    <br>
    Cheers,<br>
    Eric
  </div>

</blockquote></div>
</blockquote></div></div>