Skip to content
Latchkey

Java "module X does not read module Y" (JPMS) - Fix in CI

Under the Java Platform Module System, a module can only use types from modules it explicitly reads. Your module-info.java is missing a requires for a module whose types your code uses, so compilation (or launch) fails.

What this error means

javac fails with module com.example.app does not read module com.fasterxml.jackson.databind, or the equivalent at runtime. The type is on the module path but not readable because no requires declares the edge.

java
src/main/java/module-info.java:1: error: module com.example.app does not
read module com.google.gson
    Gson gson = new Gson();
    ^
1 error

Diagnose it: which JDK is the build actually using?

JVM builds resolve a toolchain from several sources, and the one on PATH is often not the one compiling your code. A version mismatch surfaces as an unsupported class file version rather than as a toolchain error.

Terminal
java -version 2>&1
echo "JAVA_HOME=$JAVA_HOME"
./gradlew -q javaToolchains 2>/dev/null || mvn -v

# class file 65 = Java 21, 61 = Java 17, 55 = Java 11
javap -verbose <SomeClass>.class | grep "major version"

Common causes

Missing requires directive

Your module uses a type from another module but module-info.java does not declare requires that.module.

Wrong module name

The requires uses the jar name rather than the actual module name (automatic module name differs from the artifact id).

Transitive readability not propagated

A dependency exposes a type from a third module in its API but did not declare requires transitive, so you cannot read it implicitly.

How to fix it

Add the requires directive

Declare the module your code reads.

Java
module com.example.app {
  requires com.google.gson;   // now readable
}

Use the correct module name

Find the real module name rather than guessing from the jar.

Terminal
jar --describe-module --file gson-2.11.0.jar
# prints the module name to put in requires

Request transitive readability where appropriate

If your module re-exposes a type in its own API, use requires transitive.

Java
module com.example.app {
  requires transitive com.google.gson;
}

How to prevent it

  • Keep module-info.java in sync with the types each module actually uses.
  • Resolve module names with jar --describe-module, not the jar filename.
  • Use requires transitive only when re-exposing a type in your API.

Frequently asked questions

What causes Java "module X does not read module Y" (JPMS)?
There are 3 common causes: missing requires directive, wrong module name, and transitive readability not propagated. Your module uses a type from another module but module-info.java does not declare requires that.module.
How do I fix Java "module X does not read module Y" (JPMS)?
There are 3 fixes depending on which cause you have: add the requires directive, use the correct module name, and request transitive readability where appropriate. Work through them in order, since the first is the most common.
What does Java "module X does not read module Y" (JPMS) actually mean?
javac fails with module com.example.app does not read module com.fasterxml.jackson.databind, or the equivalent at runtime.
How do I stop Java "module X does not read module Y" (JPMS) happening again?
Keep module-info.java in sync with the types each module actually uses. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card