Gradle & Code Quality

Resolve Gradle Dependency Conflicts with dependencyInsight

A dependency conflict occurs when the graph requests incompatible or different versions of a module. The declaration nearest the error is not necessarily the dependency that Gradle selected.

By , FounderUpdated 3 min read

Ask why a version was selected

Use dependencyInsight for the affected configuration:

BASH · REFERENCE EXAMPLE
./gradlew :app:dependencyInsight \
  --dependency example-library \
  --configuration releaseRuntimeClasspath

Replace the placeholder with the relevant module name. The dependency-report documentation explains selection reasons and dependency paths.

Read the graph, not just the build file

A platform, constraint, transitive dependency or resolution rule can influence selection. Two visible declarations are only part of the story.

Compare the selected version with the requirements of the libraries that use it. A build can resolve successfully and still fail at runtime if a consumer expects an API that the selected version does not provide.

Choose the least surprising correction

Cause Prefer
Misaligned family of libraries Publisher-supported platform or compatible set
Obsolete direct dependency Reviewed version update
Unnecessary transitive module Narrow exclusion with runtime verification
Different versions required by incompatible consumers Upgrade or replace a consumer

Forcing a version globally should be an explicit compatibility decision, not the first reaction.

Avoid fixing one variant while breaking another

Inspect release and debug graphs, plus relevant test configurations. Product flavors can bring in different SDKs, and an exclusion that helps one flavor may remove a needed class from another.

The Android dependency guide provides configuration context. Keep the reason for any constraint or exclusion next to the declaration or in a linked build note.

Prove the resolved outcome

Re-run the report, build the release and exercise the dependent feature. APKLint's Gradle tools can flag suspicious declarations and support review, but only Gradle's resolved graph shows which version your actual repositories and rules selected.

Turn a runtime symptom into a compatibility question

Imagine a checkout SDK calls a method introduced in codec version 2, while a build rule forces codec version 1. The graph can resolve and the app can launch, yet checkout fails when the missing method is reached. Capture the missing class or method signature and identify the calling SDK. Then compare the selected codec artifact with the API that caller expects. This is more precise than changing every library to its latest version.

The Gradle constraints and conflict guide describes how requirements influence selection. A selected version is a resolution outcome, not a guarantee that every consumer was tested with that combination. In the hypothetical case, remove or update the incompatible force only after checking the publisher's supported combination and the other consumers affected by the change.

Keep the competing requirements visible

Create a short decision record with the two requesting parents, their requested versions, the selected result and the rule that caused selection. Include why the proposed combination is supported. If a newer codec breaks an older analytics SDK, the real solution may require upgrading or replacing that SDK too. Forcing the older version to make analytics work would simply move the failure back to checkout.

Test the features that exercise both sides of the conflict using synthetic data. A unit test mocking the codec does not establish binary compatibility with the packaged artifact. Include a release build when shrinking changes the reachable code, and inspect any flavor that uses a different payment or analytics provider. Keep before-and-after reports so reviewers can see the actual selected versions instead of inferring them from declarations.

When the correction uses a constraint, document its compatibility rationale and planned review trigger. An unexplained global rule tends to survive long after the original problem disappears. Avoid labeling an exception temporary without an owner or condition for removal. The useful outcome is a build whose dependency choices are explainable and whose affected runtime paths work together, not merely a graph that stops printing a warning.

Sources and further reading

  1. Gradle: Viewing and debugging dependencies
  2. Android Developers: Add build dependencies

Reference review: 29 September 2026. Examples illustrate the workflow; check your installed versions, release artifact and account-specific Console requirements before applying them. This guide is not a claim that APKLint executed your project or verified your private account.

APKLint

Android inspection tools and practical release guides. About APKLint · Report a correction