Skip to content

DefaultProgress carries two scope annotations, so 1.3.0 breaks every mojo in a plugin realm #127

Description

@slachiewicz

DefaultProgress in 1.3.0 carries both @Singleton and @MojoExecutionScoped. Guice rejects two scope
annotations on one class, so the injector for any class realm that contains the jar fails at
construction. The realm ends up with no bindings, and Maven cannot load a single mojo out of the plugin.

A plugin that ships plexus-build-api 1.3.0 on its realm is completely dead. Not degraded — every goal in
it fails, including goals that never touch the build API.

Reproduction

Three lines in any POM, against a plugin that does nothing with plexus-build-api:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-clean-plugin</artifactId>
  <version>3.4.1</version>
  <dependencies>
    <dependency>
      <groupId>org.codehaus.plexus</groupId>
      <artifactId>plexus-build-api</artifactId>
      <version>1.3.0</version>
    </dependency>
  </dependencies>
</plugin>

mvn clean then reports:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:3.4.1:clean (default-clean)
        on project pba-repro: Execution default-clean of goal
        org.apache.maven.plugins:maven-clean-plugin:3.4.1:clean failed: Unable to load the mojo 'clean'
        (or one of its required components) from the plugin
        'org.apache.maven.plugins:maven-clean-plugin:3.4.1': java.util.NoSuchElementException
[ERROR]       role: org.apache.maven.plugin.Mojo
[ERROR]   roleHint: org.apache.maven.plugins:maven-clean-plugin:3.4.1:clean

NoSuchElementException is the symptom, not the cause. With -e the real failure appears, logged as a
warning while the realm is built:

[WARNING] ClassRealm[plugin>org.apache.maven.plugins:maven-clean-plugin:3.4.1, ...]
com.google.inject.CreationException: Unable to create injector, see the following errors:

1) [Guice/DuplicateScopeAnnotations]: More than one scope annotation was found: Singleton and MojoExecutionScoped.
  at ClassRealm[plugin>org.apache.maven.plugins:maven-clean-plugin:3.4.1, ...]
      \_ installed by: WireModule -> PlexusBindingModule

1 error

======================
Full classname legend:
======================
MojoExecutionScoped:         "org.apache.maven.execution.scope.MojoExecutionScoped"
PlexusBindingModule:         "org.eclipse.sisu.plexus.PlexusBindingModule"
Singleton:                   "javax.inject.Singleton"
WireModule:                  "org.eclipse.sisu.wire.WireModule"
========================
End of classname legend:
========================

    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist (Errors.java:576)
    ...
    at org.codehaus.plexus.DefaultPlexusContainer.addPlexusInjector (DefaultPlexusContainer.java:438)
    at org.codehaus.plexus.DefaultPlexusContainer.discoverComponents (DefaultPlexusContainer.java:416)

Every Maven line is affected. Verified on the same reproducer, JDK 25:

plexus-build-api Maven 3.9.16 Maven 3.10.0-rc-1 Maven 4.0.0-SNAPSHOT
1.2.0 pass pass pass
1.3.0 fail fail fail

Root cause

DefaultProgress declares a qualifier and two scopes. From javap -v on the class in
plexus-build-api-1.3.0.jar as published to Central:

public class org.codehaus.plexus.build.progress.DefaultProgress implements org.codehaus.plexus.build.progress.Progress
  ...
RuntimeVisibleAnnotations:
  0: #91(#92=s#93)
    javax.inject.Named(
      value="default"
    )
  1: #94()
    javax.inject.Singleton
  2: #95()
    org.apache.maven.execution.scope.MojoExecutionScoped

No other component in the jar has that combination — DefaultBuildContext, EventListener,
TcpBuildConnection, and DefaultMessages are all @Named plus @Singleton only.

What turns that into a hard failure in 1.3.0 is the sisu index. META-INF/sisu/javax.inject.Named grew
from one entry to five:

 org.codehaus.plexus.build.DefaultBuildContext
+org.codehaus.plexus.build.connect.EventListener
+org.codehaus.plexus.build.connect.TcpBuildConnection
+org.codehaus.plexus.build.messages.DefaultMessages
+org.codehaus.plexus.build.progress.DefaultProgress

Sisu scans that index for every realm the jar lands on, so DefaultProgress is now offered to Guice
everywhere, and the whole injector is rejected along with it.

Where it came from

Commit 2e729e0 ("Add a Progress API", #98, merged 2025-09-27) introduced DefaultProgress with both
scope annotations from the first revision. 1.3.0 is the first release to carry it.

master still has all three annotations today, so the drafted 1.3.1 does not fix this either.

Blast radius

The published artifact is broken for every consumer that puts it on a plugin realm, and Dependabot is
already proposing the bump. Confirmed consumers of org.codehaus.plexus:plexus-build-api on default
branches:

  • apache/camel manages the version centrally in parent/pom.xml as plexus-build-api-version = 1.2.0,
    consumed by eight Maven plugins: camel-package-maven-plugin, bom-generator-maven-plugin,
    sync-properties-maven-plugin, camel-api-component-maven-plugin,
    camel-eip-documentation-enricher-maven-plugin, camel-yaml-dsl-maven-plugin,
    camel-servicenow-maven-plugin, and camel-salesforce-maven-plugin. One property bump breaks all eight.
  • apache/camel-spring-boot camel-spring-boot-generator-maven-plugin and
    camel-spring-boot-config-generator-maven-plugin.
  • apache/aries blueprint-maven-plugin.
  • apache/maven-assembly-plugin. The open Dependabot bump,
    apache/maven-assembly-plugin#1361, fails
    288 of 290 integration tests. The base branch is green.
  • codehaus-plexus/modello, open Dependabot bump
    #599.

Consumers still on the legacy org.sonatype.plexus:plexus-build-api coordinates — among them CXF, Karaf,
Felix's maven-bundle-plugin, Dubbo, Gora, and most apache/maven-* plugins — are unaffected until they
migrate.

Suggested fix

Drop @Singleton from DefaultProgress and keep @MojoExecutionScoped. The class injects
org.apache.maven.plugin.MojoExecution through its constructor, which cannot be a singleton dependency,
so @MojoExecutionScoped is the annotation that matches the design and @Singleton is the mistake.

Verified: rebuilding plexus-build-api-1.3.0 with only @Singleton removed makes the reproducer above
pass on all three Maven versions.

Please release the fix as 1.3.1 promptly, and consider marking 1.3.0 as broken on Central so consumers
stop being offered it.

Not the same as #125

#125 is a separate 1.3.0 regression:
DefaultBuildContext gained a LegacySupport constructor dependency and can no longer be provisioned
outside a Maven session. That one bites consumers who use the container without a build. This one bites
every plugin, inside a build, before any code of theirs runs. Both should be fixed before 1.3.1.

This issue was created with AI assistance.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions