Diagnose Clojure setup failures caused by mismatched JDKs, `JAVA_HOME`, IDE runtimes, Maven or Gradle toolchains, and class files compiled for newer Java versions.
Most Clojure code runs on the same JVM your Java code runs on, so Java version conflicts look familiar: the terminal uses one JDK, the editor uses another, Maven or Gradle picks a third, and a class file was compiled for a newer runtime than the one trying to load it.
Start by identifying the actual JVM used by the failing command. Do not assume JAVA_HOME, the IDE, and the shell agree.
| Symptom | Likely cause |
|---|---|
UnsupportedClassVersionError |
A class was compiled for a newer JVM than the runtime currently loading it. |
| REPL works in terminal but fails in IDE | Editor REPL command or project JDK differs from terminal JDK. |
Maven tests use one Java version and clojure uses another |
Build tool, shell, and version manager are not aligned. |
| Native library or TLS failures appear only on one machine | Vendor distribution, architecture, trust store, or old JDK patch level differs. |
JAVA_HOME looks correct but java is wrong |
PATH is finding a different java executable first. |
Run these from the same terminal and project directory where the failure occurs:
1java -version
2javac -version
3which java
4which javac
5echo "$JAVA_HOME"
6clojure --version
7clojure -Spath
On macOS, this is also useful:
1/usr/libexec/java_home -V
For Maven and Gradle, ask the tool directly:
1mvn -version
2./gradlew --version
The question is not “what Java do I have installed?” The question is “what Java did this exact command use?”
JAVA_HOME and PATHJAVA_HOME should point to the JDK root. PATH should put that JDK’s bin directory before older or unrelated Java installations.
1export JAVA_HOME=/path/to/jdk
2export PATH="$JAVA_HOME/bin:$PATH"
3
4java -version
5javac -version
On macOS with the system helper:
1export JAVA_HOME=$(/usr/libexec/java_home -v 21)
2export PATH="$JAVA_HOME/bin:$PATH"
Use the version required by your project, not the newest version on your machine. Java 21 remains a common baseline in many JVM teams; Java 25 is also a long-term-support target in many current Java estates. The practical rule is to match the project and CI, then upgrade deliberately.
SDKMAN!, jEnv, asdf, Homebrew, IDE settings, Maven toolchains, and Gradle toolchains can all influence Java selection. Pick one team-supported policy and document it.
| Tooling choice | Good use |
|---|---|
| SDKMAN! | Developers need quick per-shell switching across JDK distributions. |
| jEnv | Teams want directory-local Java selection layered on installed JDKs. |
| Maven toolchains | Maven builds must compile or test with a specific JDK independent of shell defaults. |
| Gradle toolchains | Gradle should select a Java language/runtime version reproducibly. |
| IDE project SDK | Editor REPL and tests must match the command-line project JDK. |
If a tool changes Java selection, add it to the diagnostic list. Hidden version selection is what makes these failures expensive.
UnsupportedClassVersionErrorThe JVM throws UnsupportedClassVersionError when it tries to read a class file whose class-file version is not supported by the current runtime. In practical terms: something was compiled with a newer Java version than the runtime can load.
Work through this order:
java -version from the failing command path.mvn -version, ./gradlew --version, or CI logs.For Clojure projects, remember that Java dependencies can trigger this even when your own Clojure source has no Java compilation step.
| Runtime surface | What to verify |
|---|---|
| Terminal REPL | The shell PATH, JAVA_HOME, and clojure --version. |
| IntelliJ/Cursive | Project SDK, module SDK, and REPL run configuration. |
| VS Code/Calva | The command Calva uses to start the REPL and its working directory. |
| Maven | mvn -version, compiler settings, and toolchains. |
| Gradle | ./gradlew --version, Java toolchain config, and daemon reuse. |
| CI | The setup step that installs/selects Java before tests run. |
When in doubt, make CI the source of truth. Match local tools to CI rather than debugging every machine as a separate environment.