Safeguard
Developer Tools•

Gradle dependency locking: how to enable it and update locks

Turn on Gradle dependency locking, write gradle.lockfile, update selected modules and choose between default, strict and lenient lock modes.

Safeguard Security Team
3 min read

Gradle dependency locking records the exact versions your build resolved, so a dynamic version such as 5.+ stops changing under you. Enable it per configuration or for all of them, generate the lock with the write-locks flag, and commit gradle.lockfile.

Why lock at all

The Gradle documentation explains that dynamic versions can make builds break without any code change, because what they resolve to shifts over time. A lock keeps builds with the same inputs on the same versions. It also keeps task inputs stable for the build cache.

Turning it on

One configuration:

configurations.compileClasspath {
    resolutionStrategy.activateDependencyLocking()
}

All project configurations:

dependencyLocking {
    lockAllConfigurations()
}

That does not cover buildscript configurations. For the buildscript classpath, activate locking inside the buildscript block. You can opt a single configuration out with deactivateDependencyLocking.

Writing and updating the lock

Run the gradlew dependencies task with the write-locks option. It creates or overwrites lock state for each configuration resolved in that run. Gradle does not write lock files if the build fails.

To lock every configuration at once, add a custom task that resolves all resolvable configurations and run it with the write-locks flag.

To update only some modules, use the update-locks flag with a comma separated list. Wildcards are allowed in group or module names.

The lockfile itself

The file is gradle.lockfile in each project root, and buildscript-gradle.lockfile for the buildscript. Each line lists group, artifact and version, plus the configurations that include it, sorted alphabetically. The docs say to commit it. You can change its name or location with the lockFile property.

Lock modes

  • Default: every locked entry must match what resolves, and resolution cannot include extra dependencies beyond the lock state.
  • Strict: adds a failure when a locked configuration has no lock state.
  • Lenient: still pins dynamic versions, but allows added or removed dependencies and shifting transitive versions.

What happens on mismatch

In default mode, the build fails if a locked version differs from what resolves, a locked module is missing, or new dependencies appear that the lock does not list. If you declare a direct version higher than the locked one, resolution fails until you update the lock.

That failure is the point. It turns silent drift into a visible change someone has to approve.

A workable routine

  1. Enable locking and generate the first lock on a clean build.
  2. Commit gradle.lockfile.
  3. Update modules deliberately with update-locks, one concern per pull request.
  4. Read the lockfile diff in review. Each changed line is a version change.
  5. Schedule a regular refresh, so locks do not rot and leave you on old versions.

Locks make builds reproducible, but they also freeze vulnerable versions in place. Pair them with continuous monitoring, so a newly disclosed advisory against a locked version reaches you.

Click through it at your own pace, or open it full screen.

Safeguard's SBOM and dependency scanning can be tried free at gold.safeguard.sh/scan. For a related read, see fixing vulnerabilities in Gradle projects.

Quick check

Should gradle.lockfile be committed?

Yes. The Gradle documentation says to commit it to source control.

Why did my build fail after I raised a version?

A direct version higher than the locked one fails resolution. Update the lock state to fix it.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.