apache/maven · error · PluginContainerException
Unable to load the mojo '${mojoDescriptor.getGoal()}' in the
Error message
Unable to load the mojo '${mojoDescriptor.getGoal()}' in the plugin '${pluginDescriptor.getId()}'. A required class is missing: ${cause.getMessage()} What it means
Maven built the plugin's class realm but could not load the mojo class because a class it references is absent from that realm. DefaultMavenPluginManager walks the cause chain to the first NoClassDefFoundError/ClassNotFoundException and throws PluginContainerException, appending a dump of every jar/URL in the plugin realm so you can see which artifact should have supplied the missing class. The class name after 'A required class is missing:' is the key diagnostic.
Source
Thrown at impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java:708
T mojo;
try {
mojo = container.lookup(mojoInterface, mojoDescriptor.getRoleHint());
} catch (ComponentLookupException e) {
Throwable cause = e.getCause();
while (cause != null && !(cause instanceof LinkageError) && !(cause instanceof ClassNotFoundException)) {
cause = cause.getCause();
}
if ((cause instanceof NoClassDefFoundError) || (cause instanceof ClassNotFoundException)) {
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
PrintStream ps = new PrintStream(os);
ps.println("Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '"
+ pluginDescriptor.getId() + "'. A required class is missing: "
+ cause.getMessage());
pluginRealm.display(ps);
throw new PluginContainerException(mojoDescriptor, pluginRealm, os.toString(), cause);
} else if (cause instanceof LinkageError) {
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
PrintStream ps = new PrintStream(os);
ps.println("Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '"
+ pluginDescriptor.getId() + "' due to an API incompatibility: "
+ e.getClass().getName() + ": " + cause.getMessage());
pluginRealm.display(ps);
throw new PluginContainerException(mojoDescriptor, pluginRealm, os.toString(), cause);
}
throw new PluginContainerException(
mojoDescriptor,
pluginRealm,
"Unable to load the mojo '" + mojoDescriptor.getGoal()
+ "' (or one of its required components) from the plugin '"
+ pluginDescriptor.getId() + "'",
e);View on GitHub (pinned to e4093d4e12)
Solutions
- Read the realm dump in the message: find the class named after 'A required class is missing:' and check which artifact in the dump (or missing from it) should contain it.
- Delete the suspect artifact directory under ~/.m2/repository and rebuild with mvn -U so it is re-downloaded and checksum-verified.
- Remove or narrow <exclusions> declared on the plugin (or its parent pluginManagement) so the required transitive jar returns to the realm.
- Pin the correct version of the missing library under <plugin><dependencies> if another plugin dependency pulls an incompatible subset.
- Upgrade or downgrade the plugin to a version whose dependency set resolves cleanly in your environment.
Example fix
// before: blanket exclusion strips a jar the mojo needs
<plugin>
<groupId>org.example</groupId>
<artifactId>example-maven-plugin</artifactId>
<version>1.2.0</version>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>example-spi</artifactId>
<version>1.4.0</version>
<exclusions>
<exclusion><groupId>*</groupId><artifactId>*</artifactId></exclusion>
</exclusions>
</dependency>
</dependencies>
</plugin>
// after: drop the wildcard exclusion so the missing class is back on the plugin classpath
<plugin>
<groupId>org.example</groupId>
<artifactId>example-maven-plugin</artifactId>
<version>1.2.0</version>
</plugin> Defensive patterns
Strategy: try-catch
Validate before calling
# pre-flight: force full plugin resolution and drop zero-byte stubs before the real build mvn -B dependency:resolve-plugins find ~/.m2/repository -name '*.jar' -size -1b -print -delete mvn -U verify
Type guard
static boolean missingClassInMojoRealm(PluginContainerException e) {
Throwable c = e.getCause();
return c instanceof NoClassDefFoundError || c instanceof ClassNotFoundException;
} Try / catch
try {
Object mojo = pluginManager.getConfiguredMojo(mojoDescriptor, pluginRealm, session, mojoExecution);
} catch (PluginContainerException e) {
Throwable c = e.getCause();
if (c instanceof NoClassDefFoundError || c instanceof ClassNotFoundException) {
// classpath hole: e.getMessage() already embeds the plugin realm dump
reportPluginClasspathHole(e);
}
throw e;
} Prevention
- Pin explicit versions for every plugin so the realm composition is reproducible.
- Never use wildcard <exclusions> on plugin dependencies; exclude one artifact at a time.
- Run CI builds against a pristine local repository so corrupt jars surface immediately.
- After interrupted downloads, clean the affected group under ~/.m2/repository before the next build.
When it happens
Trigger: Calling mojo execution (direct goal invocation, lifecycle phase, or embedder getConfiguredMojo) when the plugin realm lacks a jar: a blanket <exclusions> on the plugin or its dependency, dependency mediation dropping a transitive jar, an optional/provided dependency that is not present, or a corrupted/zero-byte jar in the local repository.
Common situations: Copy-pasted <exclusions> with groupId/artifactId wildcards in pluginManagement; interrupted downloads leaving broken jars in ~/.m2/repository; running with -o (offline) against a partially cached plugin; plugin version expecting a library that a pinned older dependency shadows.
Related errors
- A required class was missing while executing {}: {}
- A required class was missing during configuration of mojo ${
- An API incompatibility was encountered while executing ${moj
- The version cannot be empty.
- %nThere can only be one user supplied ConfigurationProcessor
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/e5e4e9452bab79d6.
Report an issue: GitHub.