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()}' due to an API incompatibility: ${e.getClass().getName()}: ${cause.getMessage()} What it means
The mojo failed to load with a LinkageError that is not a missing class: NoSuchMethodError, NoSuchFieldError, AbstractMethodError, IllegalAccessError, VerifyError, and similar. The classes exist in the plugin realm but are binary-incompatible with what the plugin was compiled against, so DefaultMavenPluginManager throws PluginContainerException including the original error class, its message, and a dump of the plugin realm. This is almost always a wrong library version on the plugin classpath, not a code bug in your build.
Source
Thrown at impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java:717
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);
}
if (mojo instanceof ContextEnabled contextEnabledMojo) {
MavenProject project = session.getCurrentProject();
Map<String, Object> pluginContext = session.getPluginContext(pluginDescriptor, project);
if (pluginContext != null) {
pluginContext.put("project", project);View on GitHub (pinned to e4093d4e12)
Solutions
- Read the message: the error class (e.g. NoSuchMethodError) names the missing member and its declaring class; search the realm dump for which artifact currently supplies that class.
- Pin the version the plugin expects under <plugin><dependencies> so the realm resolves the compatible build.
- Upgrade the plugin to a version aligned with the rest of your dependency stack.
- Run mvn -X (debug) to see the exact realm composition and mediation decisions if the dump is ambiguous.
- If the error mentions a JDK-internal class, move Maven itself onto the JDK the plugin requires.
Example fix
// before: mediation pulls guava 19.0 into the realm, plugin compiled against 32.x -> NoSuchMethodError
// after: pin the matching version inside the plugin block
<plugin>
<groupId>org.example</groupId>
<artifactId>example-maven-plugin</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>
</dependencies>
</plugin> Defensive patterns
Strategy: try-catch
Validate before calling
# pre-flight: dump the resolved plugin classpath and look for unexpected versions of conflict-prone libraries mvn -X dependency:resolve-plugins 2>&1 | grep -E 'guava|commons-|asm' | sort -u
Type guard
static boolean binaryIncompatibleMojo(PluginContainerException e) {
Throwable c = e.getCause();
return c instanceof LinkageError && !(c instanceof NoClassDefFoundError);
} Try / catch
try {
Object mojo = pluginManager.getConfiguredMojo(mojoDescriptor, pluginRealm, session, mojoExecution);
} catch (PluginContainerException e) {
if (e.getCause() instanceof LinkageError le && !(le instanceof NoClassDefFoundError)) {
// NoSuchMethodError/NoSuchFieldError/... : pin the conflicting library inside <plugin><dependencies>
reportVersionConflict(le);
}
throw e;
} Prevention
- Declare critical shared libraries explicitly inside <plugin><dependencies> rather than relying on mediation.
- Upgrade plugins together as a set so their shared dependency versions stay aligned.
- Keep the JDK running Maven current enough for the newest plugin you use.
- Watch Maven's 'duplicate declared dependency' style warnings during plugin resolution.
When it happens
Trigger: Dependency mediation inside the plugin realm selects an older/newer version of a library (Guava, commons-*, ASM, SLF4J) than the plugin requires; a library duplicated across plugin dependencies; plugin compiled against a JDK API not present in the JDK running Maven.
Common situations: Two plugins (or a plugin and its dependency) forcing different versions of the same library; upgrading one plugin while pinning a shared dependency; running a modern plugin on an EOL JDK; shaded plugins with duplicate classes.
Related errors
- An API incompatibility was encountered during configuration
- An API incompatibility was encountered while executing ${moj
- A required class was missing while executing {}: {}
- A type incompatibility occurred while executing ${mojoDescri
- No plugin descriptor found at ${pluginDescriptorLocation}
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/31a44ac9ef4baf2c.
Report an issue: GitHub.