apache/maven · error · PluginContainerException
Unable to load the mojo '${mojoDescriptor.getGoal()}' (or on
Error message
Unable to load the mojo '${mojoDescriptor.getGoal()}' (or one of its required components) from the plugin '${pluginDescriptor.getId()}' What it means
Catch-all branch when mojo instantiation failed without any LinkageError in the cause chain: the container (Plexus/Sisu) could not construct the mojo or wire its components. DefaultMavenPluginManager wraps the original exception in PluginContainerException, so the real reason (missing component, unsatisfied constructor argument, exception in constructor/static initializer) is in the cause, not the headline message.
Source
Thrown at impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java:720
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);
pluginContext.put("pluginDescriptor", pluginDescriptor);
View on GitHub (pinned to e4093d4e12)
Solutions
- Re-run with mvn -e (and -X) and read the CAUSE stack trace below the PluginContainerException; it names the component or line that failed.
- If a component lookup failed, add the artifact that provides (and indexes) that component as a dependency of the plugin.
- If you own the plugin, verify the JAR packages META-INF/plexus/components.xml or META-INF/sisu/javax.inject.Named.
- Check whether the plugin version matches the versions of the libraries it injects, and align them.
- Report to the plugin project with the full stack if the plugin is unmodified third-party code.
Example fix
// before: plugin needs a Sisu component that is not on its classpath
<plugin>
<groupId>org.example</groupId>
<artifactId>example-maven-plugin</artifactId>
<version>1.0.0</version>
</plugin>
// after: add the artifact that provides (and indexes) the component
<plugin>
<groupId>org.example</groupId>
<artifactId>example-maven-plugin</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>example-spi</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
</plugin> Defensive patterns
Strategy: try-catch
Validate before calling
# pre-flight: prove the plugin and all its components load in an isolated build mvn -B -DskipTests verify -pl <module-using-plugin> -am # and smoke-test the goal directly with debug output mvn -X <goal-prefix>:<goal> | tail -100
Type guard
static boolean componentWiringFailure(PluginContainerException e) {
for (Throwable c = e.getCause(); c != null; c = c.getCause()) {
if (c instanceof LinkageError || c instanceof ClassNotFoundException) return false;
}
return true; // no linkage issue in the chain -> instantiation/DI problem
} Try / catch
try {
Object mojo = pluginManager.getConfiguredMojo(mojoDescriptor, pluginRealm, session, mojoExecution);
} catch (PluginContainerException e) {
// the original failure (missing @Named component, ctor exception) is the cause chain
Throwable root = e;
while (root.getCause() != null) root = root.getCause();
reportMojoInstantiationFailure(mojoDescriptor.getGoal(), root);
} Prevention
- For plugin authors: keep META-INF/sisu/javax.inject.Named in the shipped JAR so Sisu finds your components.
- For plugin authors: unit-test mojo instantiation with org.apache.maven.plugin.testing.MojoRule.
- For users: keep the plugin's dependency set intact; do not strip 'unused' jars.
- When upgrading plugins, read release notes for moved/renamed components.
When it happens
Trigger: Mojo declares a @Component/@Inject field for a role that no artifact in the plugin realm registers; the mojo constructor or static initializer throws a RuntimeException; the plugin was packaged without its META-INF/plexus/components.xml or Sisu index, so its own components cannot be discovered.
Common situations: Hand-built or shaded plugin JARs that lose their component descriptors; plugin depending on a library version whose @Named implementations changed; mojos that do work in static blocks failing on unusual environments; incomplete plugin upgrades where a helper component moved artifacts.
Related errors
- Error in component graph of plugin ${plugin.getId()}: ${e.ge
- Cannot read metadata from '{}'
- Unable to lookup org.eclipse.aether.RepositorySystem
- %nThere can only be one user supplied ConfigurationProcessor
- No binding to construct an instance for key {}. Existing bi
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/79d8d5faddaf78ae.
Report an issue: GitHub.