apache/maven · error · PluginExecutionException

A required class was missing while executing {}: {}

Error message

A required class was missing while executing {}: {}

What it means

Maven caught a NoClassDefFoundError while a mojo was executing: the plugin bytecode references a class that is not present in the plugin realm (the isolated classloader holding the plugin and its dependencies). Maven prints the missing-class message, dumps every artifact of the plugin realm into the error detail, wraps it in PluginContainerException and fails the build with PluginExecutionException.

Source

Thrown at impl/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java:176

            } catch (RuntimeException e) {
                throw new PluginExecutionException(mojoExecution, project, e);
            }
        } catch (MavenException e) {
            throw e;
        } catch (PluginContainerException e) {
            mojoExecutionListener.afterExecutionFailure(
                    new MojoExecutionEvent(session, project, mojoExecution, mojo, e));
            throw new PluginExecutionException(mojoExecution, project, e);
        } catch (NoClassDefFoundError e) {
            mojoExecutionListener.afterExecutionFailure(
                    new MojoExecutionEvent(session, project, mojoExecution, mojo, e));
            ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
            PrintStream ps = new PrintStream(os);
            ps.println(
                    "A required class was missing while executing " + mojoDescriptor.getId() + ": " + e.getMessage());
            pluginRealm.display(ps);
            Exception wrapper = new PluginContainerException(mojoDescriptor, pluginRealm, os.toString(), e);
            throw new PluginExecutionException(mojoExecution, project, wrapper);
        } catch (LinkageError e) {
            mojoExecutionListener.afterExecutionFailure(
                    new MojoExecutionEvent(session, project, mojoExecution, mojo, e));
            ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
            PrintStream ps = new PrintStream(os);
            ps.println("An API incompatibility was encountered while executing " + mojoDescriptor.getId() + ": "
                    + e.getClass().getName() + ": " + e.getMessage());
            pluginRealm.display(ps);
            Exception wrapper = new PluginContainerException(mojoDescriptor, pluginRealm, os.toString(), e);
            throw new PluginExecutionException(mojoExecution, project, wrapper);
        } catch (ClassCastException e) {
            mojoExecutionListener.afterExecutionFailure(
                    new MojoExecutionEvent(session, project, mojoExecution, mojo, e));
            ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
            PrintStream ps = new PrintStream(os);
            ps.println("A type incompatibility occurred while executing " + mojoDescriptor.getId() + ": "
                    + e.getMessage());
            pluginRealm.display(ps);

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Read the error detail: it names the missing class and prints the plugin realm. Check whether the artifact that should contain the class is listed, and at which version.
  2. If the artifact is absent or excluded, declare it explicitly inside the plugin's <dependencies> block (or remove the <exclusion> that dropped it).
  3. If listed at the wrong version, pin the expected version in the plugin's <dependencies> so the realm converges on it.
  4. If the jar may be corrupt, delete that artifact's folder under ~/.m2/repository and rebuild so Maven re-downloads it.
  5. Reproduce with -X to watch the realm being assembled and confirm the fix.

Example fix

<!-- before -->
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <version>3.1.0</version>
</plugin>
<!-- after: explicitly add the dependency whose classes were missing -->
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <version>3.1.0</version>
  <dependencies>
    <dependency>
      <groupId>commons-cli</groupId>
      <artifactId>commons-cli</artifactId>
      <version>1.5.0</version>
    </dependency>
  </dependencies>
</plugin>
Defensive patterns

Strategy: validation

Validate before calling

# fail fast before the real build: force-resolution of all plugin classpaths
mvn -q de.qaware.maven:go-offline-maven-plugin:2.10.0:resolve-dependencies || exit 1
# surface realm problems early (Maven 3.9+)
mvn -Dmaven.plugin.validation=VERBOSE validate 2>&1 | grep -i 'plugin'

Try / catch

// embedded usage (maven-invoker / maven-embedder)
try {
    InvocationResult r = invoker.execute(invocation);
    if (r.getExitCode() != 0) failWithMissingClassReport(r);
} catch (Exception e) {
    Throwable c = e;
    while (c.getCause() != null) c = c.getCause();
    if (c instanceof NoClassDefFoundError nc) {
        throw new IllegalStateException("plugin classpath is missing " + nc.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A mojo references a type whose jar is absent from the resolved plugin classpath: a transitive dependency was removed with <exclusions> inside the <plugin> declaration, an optional dependency of the plugin is not on the realm, the resolved dependency version no longer contains that class, or the jar in the local repository is truncated so the class entry is missing.

Common situations: Teams slimming plugin classpaths with exclusions; corrupted plugin jars after flaky downloads from a mirror; parent POMs pinning an older transitive library than the plugin expects; plugin dependencies relocated between versions.

Related errors


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