skip to content

How do you use the dependencyInsight task to find out why Gradle selected a particular version of a module?

level: middleimportance: must knowfreq 62%

answer

  1. dependencyInsight --configuration --dependency
  2. selected version + reason at top
  3. inverted/bottom-up requester tree
  4. 'by conflict resolution' reason line
  5. X -> Y means X lost

basics

~10 s

Run ./gradlew dependencyInsight --configuration <cfg> --dependency <module>. It prints the selected version, every path that requested the module, and the reason for selection — e.g. 'by conflict resolution'.

solid answer

~40 s

`dependencyInsight` is a built-in report task that explains the *resolution of one module* within one configuration. You invoke it as `./gradlew dependencyInsight --configuration runtimeClasspath --dependency guava`. It prints the **selected version** at the top, the **selection reason(s)** (e.g. `by conflict resolution: between versions 30.0 and 31.0`, `by constraint`, `forced`, `selected by rule`), and then an **inverted tree** showing every requesting path with the version each path *asked for* (`30.0 -> 31.0` meaning it lost). This is the go-to tool when highest-version-wins or `failOnVersionConflict()` surprises you: it answers both *which version won* and *who pulled it and why*. Compare with `dependencies`, which dumps the entire forward tree; `dependencyInsight` zooms into one module and adds reasons.

code

bash · 8 lines
bash
./gradlew dependencyInsight \
  --configuration runtimeClasspath \
  --dependency com.google.guava:guava

# Output highlights:
#   com.google.guava:guava:31.0-jre   (selected)
#   Selection reasons: By conflict resolution: between 31.0-jre and 30.0-jre
#   com.google.guava:guava:30.0-jre -> 31.0-jre  (this requester lost)

go deeper

for a junior

Know the command exists and that it tells you the chosen version of a module.

for a middle

Run it with --configuration and --dependency, read the selected version, the reason line, and the inverted requester tree.

for a senior

Interpret all reason types (conflict resolution, constraint, forced, selected by rule) and combine with dependencies for full diagnosis.

for a principal

Use it to set debugging conventions/runbooks for the team when resolution surprises occur in CI.

## Purpose Where `dependencies` prints the *whole* resolved graph top-down, `dependencyInsight` answers a focused question: **for this one module, what version was chosen, who requested it, and why?** It is the primary debugging tool for conflict resolution. ## Invocation ```bash ./gradlew dependencyInsight \ --configuration runtimeClasspath \ --dependency com.google.guava:guava ``` - `--configuration` (required in practice): which resolvable configuration to inspect (`compileClasspath`, `runtimeClasspath`, etc.). Resolution is per configuration, so you must say which. - `--dependency`: a substring or `group:name` matcher for the module of interest. - `--single-path` (optional): show just one requesting path instead of all. ## Reading the output Top of the report: the **selected** version and a **reason** block. Common reasons: - `by conflict resolution: between versions X and Y` — highest-wins picked this version. - `by constraint` — a dependency constraint influenced it. - `forced` — `force = true` / `resolutionStrategy.force(...)`. - `selected by rule` — a `resolutionStrategy.eachDependency` / substitution rule. Below that: an **inverted (bottom-up) tree** of every requester. A line like `com.google.guava:guava:30.0-jre -> 31.0-jre` means *this requester asked for 30.0 but the build resolved 31.0* (it lost the conflict). Each branch shows the chain of dependencies that led to the request. ## Worked example Suppose your build fails after enabling `failOnVersionConflict()` on guava. Run the insight: ``` > Task :dependencyInsight com.google.guava:guava:31.0-jre Selection reasons: - By conflict resolution: between versions 31.0-jre and 30.0-jre com.google.guava:guava:31.0-jre +--- some.lib:foo:1.0 com.google.guava:guava:30.0-jre -> 31.0-jre +--- project :app (requested com.google.guava:guava:30.0-jre) ``` Now you know: `foo` pulls 31.0, your app directly asks for 30.0, highest-wins chose 31.0. You can pin 31.0 (or upgrade your direct declaration) to resolve. ## Tips - If you omit `--configuration`, older Gradle errors out; pick the configuration that's actually failing. - For modules with the same name across groups, use the full `group:name`. - Pair it with `dependencies` for the big picture, then `dependencyInsight` to drill in.

  • What does the arrow '30.0 -> 31.0' in the report mean?
    A requester asked for 30.0 but the build resolved 31.0 for that module — i.e. 30.0 lost the conflict and was upgraded to the selected version.
  • How is dependencyInsight different from the dependencies task?
    dependencies prints the entire forward (top-down) resolved tree for configurations; dependencyInsight focuses on one module, shows the bottom-up requesters, and crucially prints the selection reason.
  • Why do you usually pass --configuration?
    Resolution is per configuration, so the selected version can differ between compileClasspath and runtimeClasspath; you must tell the task which one to report.

saying these in an interview costs you the question

  • Thinking dependencyInsight shows the whole graph — it's scoped to one module.
  • Reading 'X -> Y' as a dependency edge rather than 'X was upgraded to Y'.
  • Forgetting that the report is per configuration.

context