How to resolve module reads package error in java9
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Java 9 introduced the module system, which means the compiler and runtime now validate package visibility much more strictly than the old classpath model did. When you see a "module reads package" style error, it usually means the module graph is inconsistent: a dependency is missing, a package is not exported, or the same package appears in more than one readable module.
Read the Error as a Module-Graph Problem
A module only sees packages from modules that it reads, and only if those packages are exported. A simple modular project might look like this:
If application code imports com.example.lib.api.Service, this compiles because com.example.app reads com.example.lib, and com.example.lib exports that package.
Problems start when one of those relationships is missing. For example, if the library forgets to export the package, the application may fail during compilation with a visibility error even though the classes are physically present in the jar.
Fix Missing requires or exports
The first fix is usually in module-info.java. Check both sides:
If the package is intended only for reflection or framework use, you may need opens instead of exports. If the consumer should not depend on an internal package, move the public API into a package that the provider can safely export.
Compile with the module path, not the classpath:
Using the wrong path flag can hide the real issue because classpath and module path resolution rules are different.
If you are migrating an older application, do the conversion incrementally. First identify which jars can become real modules, then isolate libraries that still need the classpath. That staged approach makes it much easier to see whether an error comes from your own module-info.java files or from third-party jars being treated as automatic modules.
Check for Split Packages
Another common cause is a split package. That happens when the same package name exists in two different modules. JPMS rejects this because package ownership must be unambiguous.
For example, these two modules are invalid together if both contain com.example.util:
The fix is architectural, not syntactic. Move the shared package into one module, rename one package, or merge the modules. Temporary flags such as --add-reads do not solve split packages.
Useful inspection commands:
jar --describe-module shows how the jar is treated by JPMS. jdeps --check helps identify undeclared or conflicting dependencies.
Temporary Migration Flags
JPMS includes flags such as --add-reads, --add-exports, and --add-opens for compatibility work. They are useful when you need to unblock a migration, confirm a diagnosis, or keep tests running while you refactor. They should not replace proper module declarations, because the real dependency problem will remain in the build and surprise the next person who tries to run it in a cleaner environment.
Common Pitfalls
- Adding
requireson the consumer side but forgettingexportson the provider side. - Mixing classpath jars and module-path jars without understanding how automatic modules are named.
- Leaving the same package name in multiple modules, which creates a split-package error.
- Using
--add-readsor--add-exportsas a permanent fix. Those flags are best used for migration and debugging, not final design. - Importing internal packages that were never meant to be public API.
Summary
- Treat "module reads package" errors as module-graph or package-visibility problems.
- Verify both
requiresandexportsdeclarations inmodule-info.java. - Compile and run with the module path so JPMS rules apply consistently.
- Check for split packages when the same package appears in multiple modules.
- Use
jar --describe-moduleandjdepsto inspect the actual dependency graph.

