Skip to content
Latchkey

Java "InvocationTargetException" in CI - Find the Wrapped Cause

InvocationTargetException is a wrapper: a method called via reflection (frameworks, launchers, JUnit, plugin runners) threw, and reflection rethrows it boxed. The interesting failure is the cause it wraps, not the wrapper.

What this error means

A run or test fails with Caused by: java.lang.reflect.InvocationTargetException and a further Caused by: underneath (an NPE, an IllegalState, a config error). It is common from main launchers, Spring, and Gradle/Maven plugin execution.

java
Caused by: java.lang.reflect.InvocationTargetException
        at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(...)
        at org.example.Launcher.run(Launcher.java:42)
Caused by: java.lang.IllegalStateException: connection pool not initialized
        at com.example.Db.connect(Db.java:31)

Common causes

The invoked code threw an exception

Reflection cannot let an arbitrary checked/unchecked exception propagate, so it wraps it. The wrapper hides the true error until you read one level deeper.

A framework entry point failed

App launchers, plugin runners, and DI containers invoke your code reflectively; any failure inside surfaces as InvocationTargetException at the boundary.

How to fix it

Read past the wrapper to the real Caused by

  1. Scroll to the deepest Caused by: below the InvocationTargetException - that line is the real failure.
  2. Fix that root cause (missing config, NPE, bad state); the wrapper disappears once it is resolved.
  3. If logs truncate the cause, increase the framework log level to print the full chain.

Surface the cause in your own reflective calls

When you invoke reflectively, unwrap the target exception so logs show the real error.

java
try {
  method.invoke(target, args);
} catch (InvocationTargetException e) {
  throw new RuntimeException(e.getCause()); // surface the real failure
}

How to prevent it

  • Always inspect the nested Caused by, and unwrap target exceptions in your own reflection code so the underlying error is never hidden.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →