Why can the version constraints here not be satisf...
# dependency-management
v
Why can the version constraints here not be satisfied? There is one strict version and otherwise non-strict, so the strict one should be used, shouldn't it?
Copy code
> Could not resolve all files for configuration ':foo:compileClasspath'.
> Could not resolve commons-io:commons-io:{strictly 2.11.0}.
     Required by:
         project :foo > project :bar
> Cannot find a version of 'commons-io:commons-io' that satisfies the version constraints:
           Dependency path 'my.group:foo:1' --> 'my.group:bar:1' (apiElements) --> 'commons-io:commons-io:{strictly 2.11.0}'
           Dependency path 'my.group:foo:1' --> 'my.group:bar:1' (apiElements) --> 'org.apache.poi:poi-ooxml:5.4.1' (compile) --> 'commons-io:commons-io:2.18.0'
           Dependency path 'my.group:foo:1' --> 'my.group:bar:1' (apiElements) --> 'org.apache.poi:poi:5.4.1' (compile) --> 'commons-io:commons-io:2.18.0'
           Dependency path 'my.group:foo:1' --> 'my.group:bar:1' (apiElements) --> 'org.apache.poi:poi-ooxml:5.4.1' (compile) --> 'org.apache.commons:commons-compress:1.27.1' (compile) --> 'commons-io:commons-io:2.16.1'
           Dependency path 'my.group:foo:1' --> 'my.group:bar:1' (apiElements) --> 'org.apache.xmlgraphics:batik-svg-dom:1.18' (compile) --> 'org.apache.xmlgraphics:batik-awt-util:1.18' (compile) --> 'org.apache.xmlgraphics:xmlgraphics-commons:2.10' (compile) --> 'commons-io:commons-io:2.11.0'
o
Strict is more complicated than just a priority marker, it does fail resolution in certain cases where required versions are higher than the strict version. I consider this to be unintuitive behavior which should either give a better error or be removed. I've run into this myself but haven't had time to file an issue about it, so if you're able to make a minimal reproducer and report it that would be a huge help.
t
m
It is indeed arguable whether the current behavior is expected or not, and I faced this myself. That's because our mental model of
strictly
is a bit like
force
, but it's not. "stricly" is designed as "this is a strict condition that must be met". Therefore, if dependency A says "strictly 1.1" and B says "prefer 1.2", then there's no conflict and 1.1 wins. The issue is when B says "require 1.2", because the semantics of require are "it will not work with earlier releases". So, "strictly 1.1 and require 1.2" cannot be achieved.
I tend to think that we should change the behavior so that strictly wins, because that's effectively what we expect, even if it kind of breaks the contract.
v
Hm, that's strange, I always used strict versions to downgrade transitive dependencies where necessary. The workaround @Thomas Broyer referred to is not useful here, because it does not apply to downgrades as it suggests to use a strict version range instead. Actually, there must be more to the situation where that happened, unfortunately the colleague getting that error already did "things" to not get it anymore, so I'm not sure how he met that error. If I just replicate the situation that is described by the error message, resolution just works like expected, giving 2.11.0 as a result.
m
Yes, that is strange, because I'm fairly sure I've seen situations where it worked too. It's unclear to me whether it's a bug that it works, or a bug that it didn't fail. But from the "how it should work" perspective, incompatible require and strictly should fail.
v
Sure? The documentation also says:
A strict version cannot be upgraded and overrides any transitive dependency versions
m
I think it's misleading, it will not override if there's a conflict
(e.g 2 strict dependencies)
v
Yeah, for 2 strict I would also expect a failure in spite of that sentence 😄 But still strange, that it works if I model it like in the error message. Seems I have to try making my colleague replicate how he got that error, but I fear it will not be possible.
And how can this happen?
Copy code
org.bouncycastle:bcpkix-jdk18on:{strictly 1.77} -> 1.80 (c)
Or is
useTarget
in a
resolutionStrategy
overwriting strict versions?
m
resolution rules always take precedence
v
Argh, yeah, also just validated that. I wanted to use the resolution rule just for unifying the
jdk15on
,
jdk18on
, .... variants of BC to use
jdk18on
of everything and then let normal conflict resolution happen. 😞
So the
useTarget
effectively is a long version of
force
with more possibilities 🙈
https://docs.gradle.org/current/userguide/how_to_downgrade_transitive_dependencies.html did not mention that. Btw. that page also tells as "Option 1", that a strict version is the way to go for downgrading transitive dependencies. 🙂