Skip to content

3.10.x fails on org.jboss.resteasy:resteasy-client:jar:7.0.0.Final #13084

Closed

Description

@cstamas

Affected version

maven-3.10.x

Bug description

Try this:

mvn toolbox:gav-effective-model  -Dgav=org.jboss.resteasy:resteasy-client:jar:7.0.0.Final

or simpler

mvn compile

Works with 3.9.16, but fails with 3.10.x

Activity

  1. added this to the 3.10.0 milestone on Sep 9, 2026
  2. cstamas commented on Sep 10, 2026

    @cstamas
    MemberAuthor

    Here is a reproducer: https://github.com/proxy/gist.github.com/cstamas/016d2ed50c35549a68f8b25a119ce1b7

    With 3.9.16:

    [cstamas@angeleyes simple-project]$ mvn compile
    [INFO] Scanning for projects...
    [INFO] 
    [INFO] --------------------------< unknown:unknown >---------------------------
    [INFO] Building unknown 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] 
    [INFO] --- resources:3.4.0:resources (default-resources) @ unknown ---
    [INFO] skip non existing resourceDirectory /home/cstamas/tmp/simple-project/src/main/resources
    [INFO] 
    [INFO] --- compiler:3.15.0:compile (default-compile) @ unknown ---
    [INFO] No sources to compile
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  0.224 s
    [INFO] Finished at: 2026-09-10T11:11:02+02:00
    [INFO] ------------------------------------------------------------------------
    [cstamas@angeleyes simple-project]$ 
    

    With 3.10.0-SNAPSHOT:

    [cstamas@angeleyes simple-project]$ mvn compile
    [INFO] Scanning for projects...
    [INFO] 
    [INFO] --------------------------< unknown:unknown >---------------------------
    [INFO] Building unknown 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] Loaded 23729 auto-discovered prefixes for remote repository central (prefixes-central.txt)
    [WARNING] The POM for org.jboss.resteasy:resteasy-client:jar:7.0.0.Final is invalid, transitive dependencies (if any) will not be available: 9 problems were encountered while building the effective model for org.jboss.resteasy:resteasy-client:7.0.0.Final
    [ERROR] 'dependencies.dependency.version' for org.jboss.logging:jboss-logging:jar is missing. @ 
    [ERROR] 'dependencies.dependency.version' for org.jboss.logging:jboss-logging-annotations:jar is missing. @ 
    [ERROR] 'dependencies.dependency.version' for org.apache.httpcomponents:httpclient:jar is missing. @ 
    [ERROR] 'dependencies.dependency.version' for commons-codec:commons-codec:jar is missing. @ 
    [ERROR] 'dependencies.dependency.version' for org.apache.httpcomponents:httpasyncclient:jar is missing. @ 
    [ERROR] 'dependencies.dependency.version' for org.eclipse.jetty:jetty-client:jar is missing. @ 
    [ERROR] 'dependencies.dependency.version' for jakarta.ws.rs:jakarta.ws.rs-api:jar is missing. @ 
    [ERROR] 'dependencies.dependency.version' for org.reactivestreams:reactive-streams:jar is missing. @ 
    [ERROR] 'dependencies.dependency.version' for org.junit.jupiter:junit-jupiter:jar is missing. @ 
    
    [INFO] 
    [INFO] --- resources:3.5.0:resources (default-resources) @ unknown ---
    [INFO] skip non existing resourceDirectory /home/cstamas/tmp/simple-project/src/main/resources
    [INFO] 
    [INFO] --- compiler:3.15.0:compile (default-compile) @ unknown ---
    [INFO] Loaded 74 auto-discovered prefixes for remote repository apache.snapshots (prefixes-apache.snapshots.txt)
    [WARNING] Using credentials of server 'sonatype-nexus-snapshots' for repository https://oss.sonatype.org/content/repositories/snapshots, although no repository or mirror with this id is declared in settings or on the command line. Set maven.repository.credentialScope=strict to refuse such credential use.
    [WARNING] Not applying session authentication to repository sonatype-nexus-snapshots (https://oss.sonatype.org/content/repositories/snapshots) declared by a remote artifact descriptor; set aether.remoteRepositoryManager.authToDescriptorRepositories=true to restore the legacy behavior of matching credentials to such repositories by repository ID
    [INFO] No sources to compile
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  0.554 s
    [INFO] Finished at: 2026-09-10T11:11:29+02:00
    [INFO] ------------------------------------------------------------------------
    [cstamas@angeleyes simple-project]$ 
    
  3. gnodet commented on Sep 10, 2026

    @gnodet
    Contributor

    Investigation

    This reproduces with the latest Resolver 2.0.23-SNAPSHOT (post-2.0.22), not with the released 2.0.22.

    Dependency chain for resteasy-client:7.0.0.Final

    The effective model depends on a parent POM chain:

    resteasy-client:7.0.0.Final
      → parent: resteasy-jaxrs-all:7.0.0.Final
          → dependencyManagement imports BOM: resteasy-dependencies:${project.version} = 7.0.0.Final
              → defines versions for jboss-logging, httpclient, commons-codec, jetty-client, etc.
    

    When the BOM import fails (the resteasy-dependencies:7.0.0.Final POM is not resolved), versions are never injected into resteasy-client's dependencies. The effective model validator then reports ERROR: 'dependencies.dependency.version' ... is missing for each of the 9 unversioned deps → ModelBuildingException.

    Likely root cause: commit 339161be in maven-resolver

    The commit "fix: earn trust labels through verification and bind tracking to URL" (#2080) (post-2.0.22, targeting 2.0.23) introduces several changes to EnhancedLocalRepositoryManager and DefaultArtifactResolver:

    1. existenceCheckRelabel now defaults to false: previously, if an artifact was present in the local repo but not tracked for the current repository, a bare existence check would re-label it as available. Now it forces a re-download instead. This means POM artifacts in the parent/BOM chain (like resteasy-dependencies:7.0.0.Final) may fail to resolve if they are not tracked for the current session's repositories.

    2. URL-qualified tracking keys (nid_hurl format replaces the old nid format): existing tracking entries written as central= are now looked up as central-<sha1url>=. With legacyTrackingFallback=true (default) this should still work via fallback, but the interaction with existenceCheckRelabel=false may cause the issue.

    3. verifyRealPath=true by default: hasFaithfulRealPath() calls path.toRealPath() — if the local repository base path involves symlinks this can cause physically-present POMs to be treated as "not found", forcing a re-download that may fail.

    The critical path is: DefaultArtifactDescriptorReader → DefaultModelBuilder.importDependencyManagement() → DefaultModelResolver.resolveModel() → resolver.resolveArtifact(). If that resolution fails, the BOM import is silently skipped, deps have no versions, and effective model validation fails.

    Suggested investigation

    1. Run with -X and look for the resolution of org.jboss.resteasy:resteasy-dependencies:7.0.0.Final POM during model building
    2. Bisect resolver commits between 2.0.22 and current snapshot — 339161be is the prime suspect
    3. Quick workarounds to test:
      • -Daether.enhancedLocalRepository.verifyRealPath=false
      • -Daether.enhancedLocalRepository.existenceCheckRelabel=true (restores old behavior)
  4. cstamas commented on Sep 10, 2026

    @cstamas
    MemberAuthor

    Nope, maven-3.10.x current (w/ 2.0.22) also fails in same way:
    likely the cause is 03c947d

  5. gnodet commented on Sep 10, 2026

    @gnodet
    Contributor

    Root cause found: commit 03c947d8

    The culprit is 03c947d8 — "Restrict what a repository-resolved model contributes to the build", which landed on maven-3.10.x.

    What that commit does

    When a POM is built at VALIDATION_LEVEL_MINIMAL (i.e. any POM resolved from a remote repository during dependency collection — transitive deps, parents, imported BOMs), the commit suppresses profiles whose activation depends on a <property> or <file> condition. Only JDK, OS, and activeByDefault profiles survive.

    Why it breaks resteasy-client:7.0.0.Final

    The POM chain is:

    resteasy-client:7.0.0.Final
      parent → resteasy-jaxrs-all:7.0.0.Final
    

    resteasy-jaxrs-all has a profile resteasy-default with this activation:

    <activation>
      <property>
        <name>!resteasy.dependencies.eap</name>
      </property>
    </activation>

    That profile is active by default (whenever resteasy.dependencies.eap is not set, which is the normal case). Its <dependencyManagement> contains the BOM import that supplies all the missing versions:

    <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-dependencies</artifactId>
      <version>${project.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>

    With Maven 3.9.x: profile resteasy-default activates → BOM import applied → all 9 dep versions resolved ✅

    With Maven 3.10.x (after 03c947d8): resteasy-jaxrs-all is built at VALIDATION_LEVEL_MINIMAL → property-activated profiles are suppressed → resteasy-default is NOT activated → BOM import never added → 9 deps have no version → ModelBuildingException ❌

    Confirmation

    This is not a Resolver regression. The maven-3.10.x branch uses the released Resolver 2.0.22, and nothing changed there that would affect BOM resolution in this way. The 03c947d8 commit is the only change on this branch that touches profile activation for externally-resolved models.

    Fix direction

    The !property negation pattern is effectively an "active unless explicitly disabled" idiom — it's semantically equivalent to activeByDefault from the author's intent. The current restriction is too broad: it silently drops profile-managed dependency versions for any project that uses property guards on its BOM-supplying profile.

    Options:

    1. Treat !property (negated property, absent name) activation the same as activeByDefault for external models — i.e. allow it through since it's environment-independent.
    2. Widen the allowed activations to include all property activations that only check for property absence (value unset).
    3. Limit the profile suppression to only <repositories> and <pluginRepositories> contributions (not to the activation decision itself), keeping the full set of active profiles but stripping only the repo additions.

    Option 3 seems least invasive and avoids the broader question of which activations are "safe".

  6. cstamas commented on Sep 10, 2026

    @cstamas
    MemberAuthor

    Removal of property activation kills it. By doing locally this:

    diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
    index 642caef728..f0fc9d246f 100644
    --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
    +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
    @@ -525,7 +525,7 @@ private static List<Profile> withoutFileAndPropertyActivation(List<Profile> prof
             List<Profile> eligible = new ArrayList<>(profiles.size());
             for (Profile profile : profiles) {
                 Activation activation = profile.getActivation();
    -            if (activation == null || (activation.getFile() == null && activation.getProperty() == null)) {
    +            if (activation == null || activation.getFile() == null) {
                     eligible.add(profile);
                 }
             }

    It makes 3.10.x work same as 3.9.16:

    [cstamas@angeleyes simple-project]$ mvn -V compile
    Apache Maven 3.10.0-SNAPSHOT (fce34976de81bb1be7a5880a937384e556ca477f)
    Maven home: /home/cstamas/.sdkman/candidates/maven/latest-3
    Java version: 21.0.12.1, vendor: Eclipse Adoptium, runtime: /home/cstamas/.sdkman/candidates/java/21.0.12+1.1-tem
    Default locale: en_US, platform encoding: UTF-8, time zone: Europe/Copenhagen
    OS name: "linux", version: "7.2.4-200.fc44.x86_64", arch: "amd64", family: "unix"
    [INFO] Scanning for projects...
    [INFO]
    [INFO] --------------------------< unknown:unknown >---------------------------
    [INFO] Building unknown 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] Loaded 23729 auto-discovered prefixes for remote repository central (prefixes-central.txt)
    [INFO]
    [INFO] --- resources:3.5.0:resources (default-resources) @ unknown ---
    [INFO] skip non existing resourceDirectory /home/cstamas/tmp/simple-project/src/main/resources
    [INFO]
    [INFO] --- compiler:3.15.0:compile (default-compile) @ unknown ---
    [INFO] Loaded 74 auto-discovered prefixes for remote repository apache.snapshots (prefixes-apache.snapshots.txt)
    [WARNING] Using credentials of server 'sonatype-nexus-snapshots' for repository https://oss.sonatype.org/content/repositories/snapshots, although no repository or mirror with this id is declared in settings or on the command line. Set maven.repository.credentialScope=strict to refuse such credential use.
    [INFO] No sources to compile
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  0.597 s
    [INFO] Finished at: 2026-09-10T12:31:52+02:00
    [INFO] ------------------------------------------------------------------------
    [cstamas@angeleyes simple-project]$
    
  7. cstamas commented on Sep 10, 2026

    @cstamas
    MemberAuthor

    @slachiewicz @slawekjaranowski @gnodet let's discuss this
    I am for @gnodet proposed option 3, just do not allow reposes/pluginReposes enter?

    Given the same change is present on master as well, it is also affected:
    03c947d

  8. added
    priority:blockerBlocks development and/or testing work, production could not run
    on Sep 10, 2026
  9. gnodet commented on Sep 10, 2026

    @gnodet
    Contributor

    Follow-up after re-reading the code more carefully.

    Two distinct guards in 03c947d8

    The commit applies two separate restrictions to external model builds:

    1. Profile filtering (withoutFileAndPropertyActivation): profiles with <property> or <file> activation are removed from the candidate list before the selector runs — they can never activate.
    2. Repository stripping (withoutRepositories): profiles that do activate (JDK, OS, activeByDefault) have their <repositories> / <pluginRepositories> cleared before injection.

    So my earlier "option 3" (strip repos, not activation) is already what the code does for the profiles that pass filter #1. The bug is entirely in filter #1: it discards resteasy-default before the selector ever sees it.

    Why !property breaks things but isn't a security threat

    The security concern behind filter #1 is real: a property-activated profile in a transitive POM could be toggled on/off by user-supplied -D properties, letting the build environment influence what transitive code does (e.g. inject additional repositories, change dependency versions). That's a valid threat.

    But negated-property activation (<name>!foo</name>) is the opposite case. It fires when foo is absent — i.e. it's the default, "always on unless you explicitly disable me" idiom. Suppressing it doesn't prevent environment leakage into external models; it just silently breaks the model. The profile would also fire with no session properties at all.

    Concretely: resteasy-default activates when resteasy.dependencies.eap is not set. No attacker can force it to activate (it's already on by default); an attacker can only suppress it by setting that property, which makes things safer, not worse.

    Proposed fix

    In withoutFileAndPropertyActivation, treat a negated-property activation (name starts with !, no value required) as environment-independent — pass it through, just like activeByDefault:

    private static List<Profile> withoutFileAndPropertyActivation(List<Profile> profiles) {
        List<Profile> eligible = new ArrayList<>(profiles.size());
        for (Profile profile : profiles) {
            Activation activation = profile.getActivation();
            if (activation == null || (activation.getFile() == null && isSafePropertyActivation(activation.getProperty()))) {
                eligible.add(profile);
            }
        }
        return eligible;
    }
    
    /**
     * A property activation is "safe" for external models if it cannot be toggled on by
     * supplying a user/system property — i.e. it fires on property *absence* (negated name,
     * no value). Such profiles are on by default and can only be turned *off* by the
     * operator, which is the safer direction.
     */
    private static boolean isSafePropertyActivation(org.apache.maven.model.ActivationProperty prop) {
        if (prop == null) {
            return true; // no property condition at all
        }
        String name = prop.getName();
        // "!foo" with no value = active when 'foo' is absent = default-on, cannot be injected
        return name != null && name.startsWith("!") && (prop.getValue() == null || prop.getValue().isEmpty());
    }

    This keeps the security benefit (positive property conditions are still blocked) while restoring correct behaviour for the common "opt-out flag" pattern that resteasy (and presumably many other JBoss projects) relies on.

    The existing <repositories> stripping (withoutRepositories) still applies to these profiles, so the security property "external models cannot inject new repositories" is preserved.

  10. ascheman commented on Sep 10, 2026

    @ascheman
    Contributor

    Some empirical scope/severity data across the release lines (reproduced with @cstamas's gist), since it affects where the fix must land and how to test it:

    line result
    4.0.0-rc-6 (released) ✅ not affected — resolves resteasy's transitives normally
    maven-4.0.x (→ rc-7) ❌ affected, silently
    master (4.1.0-SNAPSHOT) ❌ affected, silently
    3.10.x ❌ affected — hard failure (as reported)

    rc-6 predates the change (tag 2026-07-30; 03c947d8 is 2026-09-01), so current Maven 4 users are fine. But it has reached 4.0.x and master, where — unlike 3.10.x's hard failure — it manifests as a silent drop of transitive dependencies:

    [WARNING] The POM for org.jboss.resteasy:resteasy-client:jar:7.0.0.Final is invalid, transitive dependencies (if any) will not be available: 9 problems …
       [ERROR] version missing for jboss-logging, httpclient, jakarta.ws.rs-api, …
    

    dependency:tree on 4.0.x / master lists only the direct resteasy-client jar; on rc-6 it lists jboss-logging, httpclient, jakarta.ws.rs-api, … An empty project still reports BUILD SUCCESS, but a real consumer of those transitives fails to compile / hits NoClassDefFoundError at runtime.

    Two implications:

    1. The fix needs to land on 4.0.x (before rc-7) and master (4.1.0), not just 3.10.x. Since a GitHub issue carries a single milestone (this one is 3.10.0), how would you like to track the other lines — split per line, or track them here?
    2. Because 4.0.x / master fail silently (build green, transitives gone), a regression test should assert the transitives are actually resolved (e.g. dependency:tree / classpath contains jboss-logging), not merely that the build succeeds.

    @gnodet's isSafePropertyActivation approach (pass through negated-property / default-on activations like resteasy-default, keep blocking positive ones, still strip repositories) looks right to me and should restore this case.

  11. slachiewicz commented on Sep 11, 2026

    @slachiewicz
    Member

    @ascheman woudl you be able to create regression test?

  12. slachiewicz commented on Sep 11, 2026

    @slachiewicz
    Member

    Ran the reproducer against a build of the current maven-3.10.x head (290a4a7), with and without the PR #13095 compat hunk ported to maven-model-builder (applies with -p2, two-line offset).

    Verified: 3.10.x head, dependency:tree → WARNING "POM ... is invalid", 9 missing versions, tree lists only resteasy-client
    Verified: 3.10.x head + #13095 hunk → 18 transitives, tree identical to 3.9.16
    Verified: 3.10.x head + -Dmaven.model.dependencyInterpolation.full=true → still 9 missing versions
    
    • 3.10.x does not fail hard for compile or dependency:tree; it behaves like 4.0.x (warning, green build, transitives gone). Only goals whose output is the effective model itself fail, such as toolbox:gav-effective-model.
    • maven.model.dependencyInterpolation.full is not an escape hatch: it only relaxes interpolation, the profile filter never consults it.
    • 3.10.0-rc-1 predates the change, so no released line is affected. maven-3.9.x is clean and must not receive the backport announced in the commit body until this fix lands with it.

    Prevalence, from a scan of one local repository (5800 POMs, not Central):

    Activation idiom Profiles Adding dependencies or dependencyManagement
    !name, no value 103 9
    name with !value 91 7
    positive name, no value 429 19
    name with value 235 6

    The !value hits (Guice 3.0, Apache SSHD) contribute only optional or test-scope dependencies, so measured impact is low, but it is the same default-on shape as !name.

    Questions:

    1. Fix #13084: allow negated-property profiles in external model builds #13095 is master only. I would keep this issue as the tracker and link one PR per line (maven-3.10.x, maven-4.0.x before rc-7). Objections?
    2. @gnodet should isSafePropertyActivation also accept <value>!x</value> with a positive name?
    3. @gnodet on master the changed predicate is shared with the BUILD_CONSUMER branch, so Fix #13084: allow negated-property profiles in external model builds #13095 also changes which profiles are inlined into published consumer POMs. Maven 4 (rc5) fails in maven-install-plugin due to BUILD_CONSUMER disabling profile activation for locally-resolved parent POMs #11798 wants exactly that and CI is green, but the PR body does not mention it. Intended?
    4. Fix #13084: allow negated-property profiles in external model builds #13095 tests only the compat module; the Maven 4 runtime path in maven-impl has no test for this case. Can the regression IT cover both?

    This comment was created with AI assistance.

  13. ascheman commented on Sep 13, 2026

    @ascheman
    Contributor

    @slachiewicz @gnodet

    would you be able to create regression test?

    Done — a regression test for the Maven 4 impl model builder. #13095 fixes the negated-property profile filtering in both the compat and the impl builders, but adds a test only for the compat path (maven-model-builder); this covers the impl path (maven-impl).

    Cherry-pick branch, sitting directly on #13095's head: aschemaven/maven:bugfix/13084-impl-negated-profile-test (single commit d9c6ca2).

    It builds a repository-resolved model (CONSUMER_DEPENDENCY) whose dependency POM carries a negated-property profile (!skip.defaults, default-on) plus a positive one, and asserts:

    • the negated-property profile stays active — its property and its injected dependency survive; this is the assertion that fails without the fix (expected <activated> but was <null>);
    • a repository declared inside that surviving profile is still stripped, so the activation carve-out does not reopen the repository-injection vector;
    • the positive-property profile stays filtered.

    @gnodet — easiest is to cherry-pick the single commit onto #13095 so fix + test land together; I can also open it as a stacked PR. Happy to help port tests to the other affected lines.

  14. ascheman commented on Sep 14, 2026

    @ascheman
    Contributor

    Superseded on our side: #13112's sandboxed-ProfileActivationContext approach is cleaner than the negated-only carve-out, and it already covers the Maven 4 impl path with its own tests — so my bugfix/13084-impl-negated-profile-test branch is moot, no need to cherry-pick it. 👍 for #13112 superseding #13095.

  15. cstamas commented on Sep 14, 2026

    @cstamas
    MemberAuthor

    Can we for start revert commit 03c947d (and possibly from other branches too)? As it completely blocks me in using 3.10.0-SNAPSHOT on projects using some (among others that one in this issue) dependencies?

  16. added a commit that references this issue on Sep 15, 2026
    f97b621
  17. added a commit that references this issue on Sep 16, 2026
    6bfb447
  18. added a commit that references this issue on Sep 16, 2026
    9f5f92f
  19. added 3 commits that reference this issue on Sep 16, 2026
    be80893
    ee0ed81
    cce49bc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority:blockerBlocks development and/or testing work, production could not run

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions