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

  1. Re-run with mvn -e (and -X) and read the CAUSE stack trace below the PluginContainerException; it names the component or line that failed.
  2. If a component lookup failed, add the artifact that provides (and indexes) that component as a dependency of the plugin.
  3. If you own the plugin, verify the JAR packages META-INF/plexus/components.xml or META-INF/sisu/javax.inject.Named.
  4. Check whether the plugin version matches the versions of the libraries it injects, and align them.
  5. 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

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


AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21). Data as JSON: /api/errors/79d8d5faddaf78ae. Report an issue: GitHub.