skip to content

What does `resolutionStrategy.force('com.google.guava:guava:32.1.3-jre')` do, and when would you reach for it?

level: juniorimportance: must knowfreq 58%

answer

  1. exact version override
  2. beats highest-wins
  3. configuration-level, not a declaration
  4. legacy vs constraints/strictly
  5. can downgrade

basics

~10 s

It pins Guava to exactly that version for the whole configuration, overriding whatever version conflict resolution would otherwise pick — even if another dependency wants a higher one.

solid answer

~40 s

`resolutionStrategy.force('g:a:v')` tells Gradle to resolve that module to exactly the given version, no matter what the dependency graph asks for. It overrides Gradle's default 'highest version wins' conflict resolution and any transitive requests. It's a blunt, configuration-wide override applied during resolution. You reach for it to quickly pin a transitive dependency — e.g. force a logging or JSON library to a known-good version to dodge a regression or a CVE — without touching every place it's declared. It's the legacy mechanism; modern Gradle favours `constraints` with `strictly`, which carries richer semantics and works across published metadata. But `force` is still concise for a one-off pin in an application build.

code

kotlin · 5 lines
kotlin
configurations.all {
  resolutionStrategy {
    force("com.google.guava:guava:32.1.3-jre")
  }
}

go deeper

for a junior

Know force pins an exact version and beats the default highest-version-wins.

for a middle

Explain it's a configuration-level override that can downgrade and doesn't add the dependency.

for a senior

Contrast force with constraints/strictly and explain why constraints are preferred (publishable, explicit, fail-fast).

for a principal

Frame a team policy: force only in leaf apps for incident response; constraints in platforms/BOMs for governance.

## What `force` is When Gradle builds the dependency graph it often sees the same module requested at several versions (your direct dependency wants `1.0`, a transitive wants `1.3`). By default Gradle applies **conflict resolution: highest version wins**. `resolutionStrategy.force` overrides that decision — it pins a module to an *exact* version regardless of what the graph asks for. It lives on a configuration's `ResolutionStrategy`: ```kotlin configurations.all { resolutionStrategy { force("com.google.guava:guava:32.1.3-jre") force("org.slf4j:slf4j-api:2.0.9") } } ``` ## Semantics - It is a **configuration-level override**, not a dependency declaration. It does not *add* the dependency to the graph — it only changes the version *if* the module is already there. - It wins over transitive version requests, even higher ones (downgrading is allowed). - `forcedModules` is the legacy collection behind it. ## Why modern Gradle prefers constraints `force` predates Gradle Module Metadata. It is opaque: it doesn't express *why*, can't be published, and silently overrides. The modern equivalent is a **constraint with `strictly`** (see related question), which participates in resolution as a first-class version requirement and surfaces a clear failure when something genuinely needs a conflicting version. A short-hand also exists on the dependency itself: ```kotlin implementation("com.google.guava:guava:32.1.3-jre") { isForce = true } ``` ## When to use it - A quick, local pin in an **application** (leaf) build to dodge a regression or vulnerable transitive version. - NOT in a published **library**, where consumers should keep flexibility — use constraints there instead.

  • Does `force` add the dependency if it isn't already in the graph?
    No. It only changes the resolved version of a module that is already present (directly or transitively). It is an override, not a declaration.
  • Can `force` downgrade a version?
    Yes — that's a key difference from default conflict resolution. If the graph wants 1.3 but you force 1.0, Gradle resolves to 1.0.

saying these in an interview costs you the question

  • Saying force adds a missing dependency to the graph.
  • Claiming force can never downgrade, only raise versions.
  • Recommending force inside a published library instead of constraints.

context