Debugging Module Resolution Errors in Java: A Complete Guide

Illustration for Debugging Module Resolution Errors in Java: A Complete Guide
By Last updated:

One of the most frustrating challenges developers face when adopting the Java Platform Module System (JPMS) is dealing with module resolution errors. Common issues include “package is not visible,” “module not found,” or conflicts caused by mixing classpath and module path. These errors often confuse developers transitioning from monolithic JAR deployments to modular applications.

Understanding and resolving these issues is critical in real-world projects where enterprise systems, microservices, or legacy monoliths are being modularized. Proper debugging ensures smoother builds, faster deployment pipelines, and more reliable modular applications.

Think of module resolution like a conference guest list: if someone’s name isn’t on the list, they don’t get access. If they’re on the list but don’t have the right badge, they can’t enter certain rooms. Debugging module resolution errors is about ensuring everyone is correctly listed, identified, and authorized.


Common Module Resolution Errors

1. Module Not Found

Error: module com.example.app not found

Occurs when the module path does not include the required module.

Fix:

  • Ensure the module JAR is on the --module-path
  • Verify module-info.java is correctly defined

2. Package Not Visible

Error: package com.example.internal is not visible

Occurs when trying to access a non-exported package.

Fix:

  • Export the package explicitly in module-info.java
module com.example.lib {
    exports com.example.api;   // only API is visible
}

3. Duplicate Module

Error: duplicate module: com.example.lib

Occurs when the same module appears multiple times on the module path.

Fix:

  • Remove duplicates from the module path
  • Consolidate dependencies in build tools like Maven/Gradle

4. Mixed Classpath and Module Path

Error: java.lang.module.FindException: Module not found

Occurs when dependencies are placed incorrectly on the classpath instead of module path.

Fix:

  • Place modular JARs on the module path
  • Use classpath only for non-modular libraries

5. Automatic Modules Conflicts

Automatic modules are generated when plain JARs are placed on the module path. Conflicts arise when:

  • Names clash
  • Transitive dependencies are missing

Fix:

  • Prefer modular JARs
  • Use --patch-module or modularize critical dependencies

Tools for Debugging

  • jdeps → Analyze module dependencies
jdeps --module-path mods --check com.example.app
  • --show-module-resolution → Display how modules are resolved at runtime
java --show-module-resolution -p mods -m com.example.app/com.example.Main
  • --list-modules → List all available modules in a runtime image
java --list-modules

Best Practices

✅ Always define module-info.java explicitly
✅ Use jdeps to analyze dependency graphs
✅ Keep third-party libraries modular where possible
✅ Automate checks in CI/CD pipelines
❌ Avoid relying on automatic modules long-term
❌ Don’t mix classpath and module path without care
❌ Don’t export internal packages unless absolutely necessary


What's New in Java Versions?

  • Java 5–8 → N/A (Modules introduced in Java 9)
  • Java 9 → JPMS introduced, along with common resolution challenges
  • Java 11 → Improved tooling for debugging module issues
  • Java 17 → Performance and stability improvements in JPMS
  • Java 21 → No significant updates across Java versions for this feature

Real-World Analogy

Debugging module resolution errors is like managing airport security checks. Passengers (modules) must have:

  • A valid boarding pass (declared in module-info)
  • Correct gate assignment (module path)
  • No duplicates or impersonations (duplicate modules)

If one condition fails, access is denied.


Summary & Key Takeaways

  • Module resolution errors are common during JPMS adoption
  • Errors include missing modules, visibility issues, duplicate modules, and classpath conflicts
  • Tools like jdeps and --show-module-resolution are essential for debugging
  • Follow best practices to avoid long-term headaches
  • Proper debugging ensures smooth modular deployments

FAQ: Debugging Module Resolution Errors

1. What is the difference between the classpath and module path?
Classpath loads everything without visibility rules, while module path enforces strong boundaries.

2. Why do I get “package is not visible” errors?
Because JPMS requires explicit exports declarations for package visibility.

3. What does requires transitive do?
It makes dependencies available to modules further down the chain.

4. What’s the difference between open and opens?
open opens the entire module for reflection, opens targets specific packages.

5. What are automatic modules?
Non-modular JARs treated as modules. Useful for migration but risky long-term.

6. How does JPMS improve security compared to classpath?
By enforcing strict boundaries and preventing accidental access to internals.

7. When should I use jlink vs jmod?
jmod is for packaging modules, jlink for building custom runtime images.

8. Can I modularize incrementally?
Yes, start with key components and use automatic modules as a bridge.

9. How do I handle third-party non-modular libraries?
Use them on the classpath or convert them into automatic modules.

10. Do frameworks like Spring and Hibernate support modules?
Yes, but some configurations may need tweaks for full JPMS compatibility.