<html class="apple-mail-supports-explicit-dark-mode"><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div dir="ltr"></div><div dir="ltr">Respectfully, can you give it a rest. The primary decision of Loom - that governed all others - was to make VirtualThread a Thread. Why? To ensure not just backwards compatibility but to keep a proven and robust programming model. C had errors as values from the start - what came later recognized the limitations and problems of that model and thus exceptions. Quit trying to force the rest of us back to the dark ages because you can’t figure it out. </div><div dir="ltr"><br></div><div dir="ltr">Respectfully. </div><div dir="ltr"><br><blockquote type="cite">On Dec 19, 2025, at 12:23 PM, Eric Kolotyluk <eric@kolotyluk.net> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr">

  
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  
  
    <p>Thanks — this is a thoughtful and technically grounded response,
      and I appreciate the clarity around the trade-offs STS is
      managing. I think we largely agree on the local reasoning behind
      each exception choice, and your description of STS as a compromise
      object serving orthogonal semantic needs resonates.<br>
      <br>
      I want to clarify one aspect of my intent. I’m not so much
      offering solutions here as asking questions — deliberately. In my
      experience, strong scientific and engineering work starts by
      identifying where the remaining uncertainty or friction actually
      is, before jumping to remedies. Loom itself is a good example of
      that mindset.<br>
      <br>
      One dimension that Loom brings into sharper focus is the role of
      the JVM in shaping what becomes viable or idiomatic in Java.
      Making virtual threads work required substantial runtime and
      tooling changes — including around stack capture, continuations,
      debugging, and exception mechanics — so that existing exception
      semantics continue to function naturally under a very different
      execution model. That’s an impressive achievement, but it also
      highlights an asymmetry.<br>
      <br>
      Exceptions are a VM-native failure mechanism, so when the
      execution model changes, the JVM absorbs the complexity needed to
      preserve their ergonomics. Value-based failure modeling (e.g.,
      Result-style returns) is largely a library-level pattern: it
      doesn’t require JVM enhancements to exist, but it also doesn’t
      receive first-class runtime or tooling support in the same way.
      I’m not claiming Result<T,E> is free or universally better —
      it has real costs in boilerplate and ergonomics, especially in
      Java today — only that the ecosystem naturally gravitates toward
      whatever the VM blesses as first-class.<br>
      <br>
      This context is what motivates my broader question. Structured
      concurrency makes lifetimes and scopes explicit, but failure and
      cancellation semantics are still largely ambient and
      stack-oriented. STS shows how much care is required to make that
      work well, yet it also makes visible that there are still hard
      problems here, especially once concurrency and parallelism are
      taken seriously:<br>
          •    how cancellation should be modeled and propagated,<br>
          •    how multiple concurrent failures should be aggregated or
      prioritized,<br>
          •    how to represent partial success and expected failure
      without overloading “exceptional” paths,<br>
          •    how failure semantics align with explicit lifetime
      scopes,<br>
          •    and how observability and debugging scale across async
      and parallel boundaries.<br>
      <br>
      I’m not arguing that any particular exception in STS is wrong, nor
      advocating a specific replacement model. I’m asking whether Loom’s
      success suggests that error handling — like concurrency itself —
      may still have unresolved design questions at the systems level,
      even if the current answers are pragmatic and defensible.<br>
      <br>
      If the conclusion is that exceptions remain sufficient even under
      these constraints, that’s a reasonable position. My interest is in
      making that reasoning explicit, in light of the new execution
      model Loom has introduced.<br>
      <br>
      Thanks again for engaging seriously with the question.<br>
      <br>
      Cheers,<br>
      Eric</p>
    <div class="moz-cite-prefix">On 2025-12-19 6:31 AM, David Alayachew
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAA9v-_O=ijjhr0vEtfKvRHqBqS6x+=9jHvzcenEAPB8nRzaH2A@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="auto">Hello <span class="gmail_chip gmail_plusreply" dir="auto"><a href="mailto:eric@kolotyluk.net" style="color:#15c;text-decoration:underline" moz-do-not-send="true">@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" moz-do-not-send="true" class="moz-txt-link-freetext">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" moz-do-not-send="true" class="moz-txt-link-freetext">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" moz-do-not-send="true" class="moz-txt-link-freetext">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">
                <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>
    </blockquote>
  

</div></blockquote></body></html>