Thanks for sharing your thoughts @John_McCall.
I agree with you that a system that throws exceptions all over the place (or has the potential to) is ultimately hard to deal with. I also agree that the executor is the wrong place to lay the responsibility of providing back-pressure, but I think with the current design we're implicitly doing just that.
The executor being unable to accept further jobs is a strong signal that things are getting out of hand, especially as executors will typically sit at the boundary of an application with the operating system. At that level, the most sensible option when that happens is to crash (which may be fine, but I think we should be explicit about it).
Please excuse my ignorance as I haven't invested the time needed to fully understand the concurrency proposals/pitches, so I'm not certain who calls into the executor (the task group?), but I'm wondering if there could be a feedback loop between the executor and its caller which ultimately dealt with back-pressure or errors thrown from the executor. That is, have the executor's caller use this information and, maybe combined with the programmer's intent, optimally choose what to do: retry, bubble upwards or crash.
Circling back to your first point, I think things get hard to deal with only if we choose to always bubble upwards, which was my initial proposal. But I'm hopeful that it doesn't have to be that way and seeing how these pitches embrace cancellation, maybe we can come up with an API to deal with this as well.