Skip to content
Latchkey

Clojure JDK version mismatch (setup-java) in CI

Clojure runs on the JVM, so the runner JDK must match what the project and its dependencies expect. A too-old JDK cannot load classes compiled for a newer one (UnsupportedClassVersionError); a mismatch can also change AOT bytecode targets.

What this error means

A build fails with "java.lang.UnsupportedClassVersionError: ... has been compiled by a more recent version of the Java Runtime" or behaves differently than on developer machines running another JDK.

JVM
java.lang.UnsupportedClassVersionError: com/example/Widget has been compiled by a more
recent version of the Java Runtime (class file version 65.0), this version of the Java
Runtime only recognizes class file versions up to 61.0

Common causes

The runner JDK is older than a dependency needs

A dependency compiled for a newer JDK cannot load on the older runtime the runner provides.

No pinned JDK on the runner

Without setup-java, the runner default JDK may differ from what the team develops and releases against.

How to fix it

Pin the JDK with setup-java

Provision a specific JDK before installing the Clojure tooling so the runtime matches the project.

.github/workflows/ci.yml
- uses: actions/setup-java@v4
  with:
    distribution: temurin
    java-version: '21'
- uses: DeLaGuardo/setup-clojure@13.0
  with:
    cli: latest

Align the AOT bytecode target

Set the compile target so AOT output matches the runtime you deploy on.

project.clj
:javac-options ["-source" "21" "-target" "21"]

How to prevent it

  • Pin the JDK with setup-java and match it to production.
  • Keep the local, CI, and deploy JDK versions aligned.
  • Set an explicit bytecode target for AOT builds.

Related guides

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