skip to content

What does failOnVersionConflict() do, and why might a team enable it?

level: middleimportance: should knowfreq 55%

answer

  1. ResolutionStrategy method
  2. fails instead of silently highest-wins
  3. configurations.all { resolutionStrategy ... }
  4. forces explicit pinning
  5. fails on differing requested versions

basics

~10 s

It 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 lines
kotlin
configurations.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-jre

go deeper

for a junior

Know that it makes version conflicts fail the build instead of resolving silently.

for a middle

Place it on resolutionStrategy, apply via configurations.all, and describe the diagnose-then-pin workflow.

for a senior

Discuss trade-offs (friction vs. reproducibility) and pairing it with a platform/BOM for governed versions.

for a principal

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.

context