Maven/Gradle "JAVA_HOME is set to an invalid directory" - Fix in CI
By Kaveh Alemi·Latchkey
Maven or Gradle checked JAVA_HOME and found it does not point at a valid JDK directory. The path is wrong, includes a trailing /bin, points at a JRE, or JAVA_HOME is unset entirely.
What this error means
The build script aborts at startup with The JAVA_HOME environment variable is not defined correctly / JAVA_HOME is set to an invalid directory, before Maven or Gradle does any work.
Terminal
The JAVA_HOME environment variable is not defined correctly,
this environment variable is needed to run this program.
NB: JAVA_HOME should point to a JDK not a JRE
Common causes
JAVA_HOME points at a wrong or non-existent path
A stale path, a trailing /bin (it should be the home, not the bin dir), or a directory that was removed makes JAVA_HOME invalid.
JAVA_HOME unset or pointing at a JRE
If JAVA_HOME is empty, or points at a JRE rather than a JDK, the build tool’s validation rejects it.
How to fix it
Set JAVA_HOME to a real JDK home
Let setup-java export it, or set it explicitly to the JDK home directory (not its bin).
.github/workflows/ci.yml
- uses:actions/setup-java@v4with:distribution:temurinjava-version:'21'- run:echo "JAVA_HOME=$JAVA_HOME" && ls "$JAVA_HOME/bin/java"
Fix the path in a container build
Point JAVA_HOME at the JDK home and confirm java/javac exist under it.
Terminal
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
test -x "$JAVA_HOME/bin/javac" && echo OK
How to prevent it
Use setup-java (or a JDK base image) so JAVA_HOME is set correctly.
Point JAVA_HOME at the JDK home, never its /bin subdirectory or a JRE.
Assert $JAVA_HOME/bin/javac exists early in the job.
Frequently asked questions
What causes ""JAVA_HOME is set to an invalid directory""?
A stale path, a trailing /bin (it should be the home, not the bin dir), or a directory that was removed makes JAVA_HOME invalid.
How do I fix "JAVA_HOME is set to an invalid directory"?
Let setup-java export it, or set it explicitly to the JDK home directory (not its bin).
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.