What does failOnVersionConflict() do, and why might a team enable it?
answer
- ResolutionStrategy method
- fails instead of silently highest-wins
- configurations.all { resolutionStrategy ... }
- forces explicit pinning
- fails on differing requested versions
basics
~10 sIt switches a configuration's resolution strategy so that any version conflict between transitive dependencies makes the build fail instead of silently picking the highest version, forcing the team to resolve it explicitly.
solid answer
~40 s`failOnVersionConflict()` is set on a configuration's **resolution strategy**. Normally Gradle silently applies highest-version-wins; with this flag, **any** module that ends up with more than one requested version fails the build with a `Conflict(s) found for the following module(s)` error. Teams enable it to make implicit version drift **visible and deliberate** — you can no longer accidentally ship whatever transitive version happened to be highest. The trade-off is friction: every legitimate conflict must be pinned (via constraints, forcing, or platforms — separate topics). You typically apply it across configurations using `configurations.all { resolutionStrategy.failOnVersionConflict() }`. Once it fires, you diagnose with `dependencyInsight --dependency <module>` to see who requested which version, then pin a single version.
code
kotlin · 8 linesconfigurations.all {
resolutionStrategy {
failOnVersionConflict()
}
}
// Now any module requested at two versions fails the build:
// > Conflict(s) found for the following module(s):
// > - com.google.guava:guava between versions 31.0-jre and 30.0-jrego deeper
Know that it makes version conflicts fail the build instead of resolving silently.
Place it on resolutionStrategy, apply via configurations.all, and describe the diagnose-then-pin workflow.
Discuss trade-offs (friction vs. reproducibility) and pairing it with a platform/BOM for governed versions.
Treat it as an org policy lever for supply-chain hygiene; weigh adoption cost on large graphs and incremental rollout.
## What it is `failOnVersionConflict()` is a method on `ResolutionStrategy`, reachable via a configuration: `configurations.<name>.resolutionStrategy.failOnVersionConflict()`. It changes the conflict-resolution behaviour from *resolve silently* to *fail loudly*. ## Default vs. fail-on-conflict - **Default:** when a module is requested at several versions, Gradle picks the highest and continues. No warning. - **With `failOnVersionConflict()`:** the moment resolution detects more than one version requested for a module, it aborts resolution of that configuration with an error listing the conflicting modules and versions. Note the subtlety: it fails on *requested* version differences, even when highest-wins would have resolved them cleanly. A graph where everyone already agrees on one version does **not** fail. ## Why enable it - **Reproducibility / supply-chain hygiene:** you don't want the version on your classpath to silently change because a transitive bumped. Failing forces an explicit decision. - **Catch incompatible bumps early:** highest-wins can silently pull a breaking major version; failing surfaces it before runtime. - **Policy enforcement:** larger orgs use it to require all versions be governed through a platform/BOM. ## How to apply broadly ```kotlin configurations.all { resolutionStrategy { failOnVersionConflict() } } ``` Applying to `all` is common because conflicts can occur in any resolvable configuration (`compileClasspath`, `runtimeClasspath`, test variants, etc.). ## The workflow after it fires 1. Read the error — it lists `group:name` and the conflicting versions. 2. Run `./gradlew dependencyInsight --configuration runtimeClasspath --dependency <name>` to see *who* requested *what*. 3. Pin one version (dependency constraints, a platform/BOM, or `force` — covered in adjacent topics). 4. Re-run until green. ## Caveats - It's noisy on large legacy graphs; many teams adopt it incrementally or pair it with a curated platform. - It is a build-time guard, not a runtime guarantee — it only governs what Gradle resolves. - Newer Gradle also exposes `failOnNonReproducibleResolution()` and related flags; `failOnVersionConflict()` specifically targets version conflicts.
- After failOnVersionConflict() fires, how do you find out which dependency pulled the conflicting version?Run dependencyInsight for that module: ./gradlew dependencyInsight --configuration runtimeClasspath --dependency guava. It prints each requesting path and the reason, so you can see who asked for which version.
- Does it fail even if highest-wins would resolve cleanly?Yes. It fails whenever more than one version is requested for a module, regardless of whether the default heuristic could have picked a winner. Agreement on a single version is required to pass.
saying these in an interview costs you the question
- Saying it forces the highest version — it does the opposite, it refuses to auto-pick.
- Thinking it's a global setting rather than per-configuration (resolution strategy).
- Claiming it only triggers when versions are actually incompatible — it triggers on any version difference.