ascheman opened a new issue, #12770: URL: https://github.com/apache/maven/issues/12770
### Summary When a plugin has no version anywhere in the effective model, Maven 4 resolves it from the repository's `RELEASE` metadata. In Maven's version semantics a `4.0.0-beta-N` **is** a release (it is not a `SNAPSHOT`), so Maven 4 selects a pre-release plugin that was compiled against an unstable Maven 4 API — and the build dies with a linkage error. Maven 3 does not have this problem: it runs a plugin compatibility check, rejects the incompatible version and falls back to the newest usable one. ### Reproducer Minimal showcase with CI: https://github.com/aschemaven/maven4-unversioned-plugin-pick Three files: a POM with no parent, no `<build>`, no `<pluginManagement>` and no plugin version anywhere, one trivial class, and a workflow running the *same* command on three setups. ```bash mvn source:jar # nothing pinned anywhere ``` `maven-source-plugin` is not part of any lifecycle binding, so the version has to come from metadata. Central currently publishes: ```xml <latest>4.0.0-beta-1</latest> <release>4.0.0-beta-1</release> ``` **Apache Maven 4.0.0-rc-6** (`6a8189b24518daa120539fa41ce12f2b48ec09a8`), JDK 17, empty local repository: ``` [INFO] --- source:4.0.0-beta-1:jar (default-cli) @ unversioned-plugin-pick --- [ERROR] Failed to execute goal org.apache.maven.plugins:maven-source-plugin:4.0.0-beta-1:jar (default-cli) on project unversioned-plugin-pick: Execution default-cli of goal org.apache.maven.plugins:maven-source-plugin:4.0.0-beta-1:jar failed: An API incompatibility was encountered while executing org.apache.maven.plugins:maven-source-plugin:4.0.0-beta-1:jar: java.lang.NoSuchMethodError: 'java.util.List org.apache.maven.api.services.ProjectManager.getCompileSourceRoots( org.apache.maven.api.Project, org.apache.maven.api.ProjectScope)' ``` **Apache Maven 3.9.16** and **3.10.0-rc-1**, same project, same command, same JDK: ``` [WARNING] Ignoring incompatible plugin version 4.0.0-beta-1: The plugin org.apache.maven.plugins:maven-source-plugin:4.0.0-beta-1 has unmet prerequisites: [INFO] Latest version of plugin org.apache.maven.plugins:maven-source-plugin failed compatibility check [INFO] Looking for compatible RELEASE version of plugin org.apache.maven.plugins:maven-source-plugin [INFO] Selected plugin org.apache.maven.plugins:maven-source-plugin:3.4.0 [INFO] BUILD SUCCESS ``` Maven 3 only escapes *this* case by accident. The beta declares Maven 4 prerequisites, so the compatibility check rejects it. The version selection itself ignores pre-release qualifiers on every line: with a plugin whose pre-release *is* compatible (staged repository, stable `1.0` and pre-release `2.0-beta-1`, metadata naming `2.0-beta-1` as `<release>`), **3.9.16 and 4.0.0-rc-6 both select `2.0-beta-1`**. That is the staged scenario of the integration test below. The CI workflow encodes exactly this contrast — `unversioned` green on 3.9.16 and 3.10.0-rc-1, **red** on 4.0.0-rc-6, `pinned-workaround` green — and runs weekly, so it keeps reflecting whatever Central currently calls `RELEASE`. ### Why this is worth fixing rather than waiting it out The symptom disappears once a stable `maven-source-plugin` 4.x is released, but the mechanism stays: any plugin whose newest published version is a pre-release becomes a trap for every build that does not pin. Two changes made this more likely than it used to be: 1. The Maven 3 super POM pinned four commonly CLI-invoked plugins in `pluginManagement` (`maven-antrun-plugin`, `maven-assembly-plugin`, `maven-dependency-plugin`, `maven-release-plugin`). Maven 3.10 and 4.x dropped that block, so more plugins now fall through to `RELEASE` resolution. 2. The compatibility fallback that saves the Maven 3 run is not a guard against pre-releases — it only checks the plugin's declared prerequisites. Under Maven 4 the beta's prerequisites are formally satisfied (it *is* Maven 4), so nothing catches the API break and the user gets a raw `NoSuchMethodError` naming an internal API method, with no hint that a version selection caused it. ### Fix Branches (fork, ready to become PRs — `https://github.com/aschemaven/maven`): * `bugfix/unversioned-plugin-prerelease` — off `master` (4.1) * `backport/40x-unversioned-plugin-prerelease` — off `maven-4.0.x` `DefaultPluginVersionResolver` is byte-identical on both lines, so the change cherry-picks cleanly. What it does: when a plugin has no declared version, prefer a version *without* a pre-release qualifier whenever the repository offers one; fall back to pre-releases, then snapshots, so a plugin that has only ever published pre-releases still resolves. A pre-release is recognised through the version scheme itself rather than a list of qualifier names: such a qualifier sorts *before* the version it qualifies (`1.0-beta-1 < 1.0`), while a build or vendor qualifier does not (`1.0-jre > 1.0`). Alternatives that were considered and are *not* in the patch, but may be worth having as well: 1. Report a comprehensible failure when an auto-selected plugin throws `NoSuchMethodError`/`NoClassDefFoundError` against `org.apache.maven.api.*` — name the version selection as the likely cause instead of surfacing the linkage error alone. 2. Re-introduce super POM `pluginManagement` pins for the handful of plugins commonly invoked from the CLI without a version (Maven 3.10 and 4.x dropped the block that Maven 3.9 still has). ### Integration test `MavenITghUnversionedPluginPrereleaseTest` + `its/core-it-suite/src/test/resources/gh-unversioned-plugin-prerelease/`. It does not depend on live Central metadata: the test stages its own plugin repository offering a stable `1.0` and a pre-release `2.0-beta-1`, with `<release>2.0-beta-1</release>` in the metadata — the same shape Central has today for `maven-source-plugin`. The project declares the plugin without a version and the test asserts the marker file written by `1.0`. Verified: | distribution | result | |---|---| | `master` + fix | IT passes; full core IT suite green (1052 tests, 0 failures) | | `master` without fix | IT fails: `Expected file was not found: target/touch-stable.txt` (the beta ran) | | `maven-4.0.x` + fix | see the backport branch | The IT class and resource directory are named after this issue once it has a number. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
