Skip to content
Latchkey

Java "IllegalAccessError" (JPMS module) in CI - Fix Module Access

IllegalAccessError at runtime usually means the module system (or a binary mismatch) blocked access to a type that compiled fine. A package is not exported/opened by the module that owns it, or two incompatible versions of a class are present.

What this error means

A run or test throws java.lang.IllegalAccessError: class A (in module m) cannot access class B (in module n) because module n does not export the package to module m.

java
java.lang.IllegalAccessError: class com.example.app.Main (in module app)
cannot access class com.example.internal.Engine (in module core) because
module core does not export com.example.internal to module app

Common causes

The package is not exported/opened to the caller

Under JPMS a package is encapsulated unless exports/opens lists it. Reflective or direct access from another module is rejected with IllegalAccessError.

Split package or duplicate class versions

The same package supplied by two modules/jars, or two versions of a class, can also surface as IllegalAccessError when the loader links the wrong one.

How to fix it

Export or open the package in module-info

Declare the access the consumer needs in the owning module.

module-info.java
module core {
  exports com.example.api;            // compile + runtime access
  opens   com.example.internal to app; // reflective access only
}

Open at launch when you cannot edit the module

Pass --add-exports / --add-opens to the test or run JVM as a stopgap.

.github/workflows/ci.yml
- run: >
    java
    --add-opens core/com.example.internal=app
    -jar app.jar

How to prevent it

  • Design module boundaries with explicit exports/opens, avoid split packages, and keep one version of each library on the module path.

Related guides

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