ExecutionException
JavaERRORNotableConcurrency
Exception thrown by async task (wrapped)
Quick Answer
Always call e.getCause() when catching ExecutionException to get the actual exception; log and rethrow the cause, not the wrapper.
What this means
Thrown by Future.get() and CompletableFuture.get() when the underlying asynchronous task threw an exception. The original exception is wrapped — access it with getCause().
Why it happens
- 1The Callable or Runnable submitted to an ExecutorService threw an exception
- 2A CompletableFuture stage threw an unchecked exception
Fix
Unwrap the cause and rethrow
Unwrap the cause and rethrow
try {
String result = future.get();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof MyDomainException mde) {
throw mde; // rethrow typed
}
throw new RuntimeException("Async task failed", cause);
}Why this works
getCause() retrieves the original exception. Pattern matching instanceof (Java 16+) allows typed unwrapping without a chain of instanceof checks.
Code examples
CompletableFuture handle()java
future.handle((result, ex) -> {
if (ex != null) {
log.error("Task failed", ex); // ex is already unwrapped
return fallback;
}
return result;
});Same error in other languages
Sources
Official documentation ↗
Java SE Documentation
Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev