Safeguard
Developer Tools•

Gradle dynamic versions: how to lock them without losing updates

Gradle dynamic versions like 1.+ can change what you build. Dependency locking records the resolved result so builds stay stable until you update.

Safeguard Security Team
4 min read

Dynamic versions such as 1.+ or a range let Gradle pick a different version over time, which can break builds with no code change. Dependency locking records the resolved versions in a lock file, so builds fail instead of drifting. You then refresh the lock on purpose.

What the Gradle documentation says

Gradle's dependency locking page warns that dynamic versions can cause builds to break unexpectedly, because the exact version that gets resolved can change over time. Locking is enabled per dependency configuration. Once it is on, you create an initial lock state, and Gradle then verifies that resolution results do not change. If the selected dependencies differ from the locked ones because newer versions exist, the build fails.

The documentation also points to a balance: teams that want the latest versions can use dynamic versions during development and testing and lock them for releases.

Turning it on

You can lock one configuration:

configurations {
    compileClasspath {
        resolutionStrategy.activateDependencyLocking()
    }
}

Or all of them at once, which the documentation notes does not include the buildscript configurations:

dependencyLocking {
    lockAllConfigurations()
}

Then write the lock state with the write-locks argument:

./gradlew dependencies --write-locks

That creates or updates the lock state for each resolved configuration. If a lock state already exists, it is overwritten. The result is a gradle.lockfile that the documentation says is generated and should not be edited by hand.

Limits you should know

Locking works with dynamic versions, but the documentation says it should not be used with changing versions such as SNAPSHOT, where the coordinates stay the same while the content may change. A lock cannot tell you the content moved.

Also, locking only applies to configurations that can be resolved. On a non-resolvable configuration it does nothing.

A workable policy

  1. Commit gradle.lockfile.
  2. Keep direct dependencies as exact versions where you can, and use dynamic versions only where you want a deliberately moving target.
  3. Use lock-aware CI so a changed resolution fails the build.
  4. Update locks in a separate pull request, with tests, and review the diff.
  5. Do not lock SNAPSHOT dependencies and expect stability. Avoid them in release builds.
ApproachRepeatableGets fixes automatically
Exact versionsYesNo, you bump them
Dynamic versions, no lockNoYes, unreviewed
Dynamic versions with lockYesWhen you refresh the lock

The third row is the useful middle: you keep a flexible declaration, but each new version arrives through a diff.

Locking is not verification

Locking says "these are the versions". It does not say the files are authentic. Gradle has a separate dependency verification feature for checksums and signatures. Use both if your risk calls for it.

Where Safeguard fits

Safeguard's dependency scanning and SBOM generation can check the versions your locked Gradle build uses against known vulnerabilities, and a free scan is available at gold.safeguard.sh/scan.

Try it yourself

Open the demo and notice how monitoring catches a newly disclosed issue in a version that was locked and unchanged.

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

Quick check

Does Gradle locking stop all updates?

No. It makes resolution changes fail the build until you refresh the lock on purpose with the write-locks argument.

Can I lock SNAPSHOT dependencies?

Gradle advises against it. The coordinates stay the same while the content may change, so a lock cannot keep it stable.

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.