Search code examples
javanullpointerexceptioncompletable-future

Cannot invoke toCompletableFuture() because the return value of apply(Object) is null while working with method that returns CompletionStage<Void>


I'm stuck on an error:

java.util.concurrent.CompletionException: java.lang.NullPointerException: Cannot invoke "java.util.concurrent.CompletionStage.toCompletableFuture()" because the return value of "java.util.function.Function.apply(Object)" is null

The line the error's pointing to is indicated below:

.handle(
    (result, ex) -> {
      if (ex == null) {
        return null;
      } else if (ex.getCause() instanceof NotFoundException) {
        return configStore.doSomething(); /** returns a CompletionStage<Void> **/
      }
      throw new CompletionException(ex.getCause());
    })
.thenCompose(x -> x); /** error points here **/

I think the .thenCompose(x -> x); is necessary because .handle(...) does not unwrap a CompletionStage<...>, resulting in a CompletionStage<CompletionStage<...>> when chaining inside the .handle(...).

To address the error I also tried returning this instead of null...

.handle(
    (result, ex) -> {
      if (ex == null) {
        return CompletableFuture.completedFuture(null); /** tried this **/
      } else if ...

...but then I get this error (screenshot for more context):

enter image description here


Solution

  • Figured it out while writing the question; self-answering because my Google and SO searches with the error message weren't pointing me to this solution.

    The solution was actually suggested by IntelliJ (blue text in the screenshot) but I didn't see it. Because null is ambiguous in type, you have to cast the expression like so:

    .handle(
        (result, ex) -> {
          if (ex == null) {
            return CompletableFuture.<Void>completedFuture(null); /** cast to <Void> **/
          } else if ...