Does an exception handler passed to CompletableFuture.exceptionally() have to return a meaningful value? : <p>I'm used to the <a href="https://github.com/google/guava/wiki/ListenableFutureExplained" rel="noreferrer"><code>ListenableFuture</code></a> pattern, with <code>onSuccess()</code> and <code>onFailure()</code> callbacks, e.g.</p>

<pre><code>ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
ListenableFuture&lt;String&gt; future = service.submit(...)
Futures.addCallback(future, new FutureCallback&lt;String&gt;() {
  public void onSuccess(String result) {
    handleResult(result);
  }
  public void onFailure(Throwable t) {
    log.error("Unexpected error", t);
  }
})
</code></pre>

<p>It seems like Java 8's <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html" rel="noreferrer"><code>CompletableFuture</code></a> is meant to handle more or less the same use case. Naively, I could start to translate the above example as:</p>

<pre><code>CompletableFuture&lt;String&gt; future = CompletableFuture&lt;String&gt;.supplyAsync(...)
  .thenAccept(this::handleResult)
  .exceptionally((t) -&gt; log.error("Unexpected error", t));
</code></pre>

<p>This is certainly less verbose than the <code>ListenableFuture</code> version and looks very promising.</p>

<p>However, it doesn't compile, because <code>exceptionally()</code> doesn't take a <code>Consumer&lt;Throwable&gt;</code>, it takes a <code>Function&lt;Throwable, ? extends T&gt;</code> -- in this case, a <code>Function&lt;Throwable, ? extends String&gt;</code>.</p>

<p>This means that I can't just log the error, I have to come up with a <code>String</code> value to return in the error case, and there is no meaningful <code>String</code> value to return in the error case. I can return <code>null</code>, just to get the code to compile:</p>

<pre><code>  .exceptionally((t) -&gt; {
    log.error("Unexpected error", t);
    return null; // hope this is ignored
  });
</code></pre>

<p>But this is starting to get verbose again, and beyond verbosity, I don't like having that <code>null</code> floating around -- it suggests that someone might try to retrieve or capture that value, and that at some point much later I might have an unexpected <code>NullPointerException</code>.</p>

<p>If <code>exceptionally()</code> took a <code>Function&lt;Throwable, Supplier&lt;T&gt;&gt;</code> I could at least do something like this --</p>

<pre><code>  .exceptionally((t) -&gt; {
    log.error("Unexpected error", t);
    return () -&gt; { 
      throw new IllegalStateException("why are you invoking this?");
    }
  });
</code></pre>

<p>-- but it doesn't.</p>

<p>What's the right thing to do when <code>exceptionally()</code> should never produce a valid value? Is there something else I can do with <code>CompletableFuture</code>, or something else in the new Java 8 libraries, that better supports this use case?</p>
