gradle/gradle · error · InvalidUserCodeException
Both dependency locking and fail on dynamic versions are ena
Error message
Both dependency locking and fail on dynamic versions are enabled. You must choose between the two modes.
What it means
ResolutionExecutor.getAllVersionLocks builds the lock set for a resolve. Dependency locking already pins every module, so the resolutionStrategy.failOnDynamicVersions() mode (also switched on by failOnNonReproducibleResolution()), whose job is to error out when dynamic versions are used, is mutually exclusive with it. When both are active Gradle fails fast with this InvalidUserCodeException instead of resolving with contradictory semantics.
Source
Thrown at platforms/software/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ResolutionExecutor.java:476
repositories,
params.getComponentMetadataRules(),
params.getVariantDerivationStrategy(),
legacyParams.getComponentSelectionRules(),
params.isDependencyVerificationEnabled(),
params.getCacheExpirationControl(),
params.getRootComponent().getMetadata().getAttributesSchema()
));
return new ComponentResolversChain(resolvers);
}
private ImmutableList<ResolutionParameters.ModuleVersionLock> getAllVersionLocks(ResolutionParameters params) {
if (!params.isDependencyLockingEnabled()) {
return params.getModuleVersionLocks();
}
if (params.isFailingOnDynamicVersions()) {
throw new InvalidUserCodeException(
"Both dependency locking and fail on dynamic versions are enabled. You must choose between the two modes."
);
} else if (params.isFailingOnChangingVersions()) {
throw new InvalidUserCodeException(
"Both dependency locking and fail on changing versions are enabled. You must choose between the two modes."
);
}
return ImmutableList.<ResolutionParameters.ModuleVersionLock>builder()
.addAll(getLockfileLocks(params))
.addAll(params.getModuleVersionLocks())
.build();
}
private ImmutableList<ResolutionParameters.ModuleVersionLock> getLockfileLocks(ResolutionParameters params) {
DependencyLockingState dependencyLockingState = dependencyLockingProvider.loadLockState(
params.getDependencyLockingId(),
params.getResolutionHost().displayName()View on GitHub (pinned to 534f27719b)
Solutions
- Remove failOnDynamicVersions()/failOnNonReproducibleResolution() from configurations that use dependency locking; the lockfile enforces reproducibility
- Keep the two modes on disjoint configurations if both are genuinely needed
- Audit convention plugins for global resolutionStrategy settings before turning on locking
Example fix
// before
configurations {
compileClasspath {
resolutionStrategy.failOnNonReproducibleResolution()
dependencyLocking { lockThisAndSubConfigurations() }
}
}
// after
configurations {
compileClasspath {
dependencyLocking { lockThisAndSubConfigurations() }
}
} Defensive patterns
Strategy: validation
Validate before calling
// Convention-plugin guard: do not enable fail-on-dynamic where lockfiles exist
allprojects {
afterEvaluate {
def hasLock = file('gradle.lockfile').exists()
if (hasLock) {
configurations.matching { it.resolutionStrategy }.all { c ->
// nothing to enforce directly; keep conventions from setting the flag
}
}
}
}
// Prefer: only set failOnDynamicVersions when locking is NOT configured
if (!project.file('gradle.lockfile').exists()) {
configurations.all { resolutionStrategy.failOnNonReproducibleResolution() }
} Prevention
- Treat dependency locking as the single reproducibility mechanism once enabled
- Audit convention plugins for failOnDynamicVersions/failOnNonReproducibleResolution before adopting locking
- Keep release-mode flags and locking on different, explicitly documented configurations
When it happens
Trigger: A configuration has dependency locking active (dependencyLocking { lockThisAndSubConfigurations() } / activateDependencyLocking(), or a gradle.lockfile exists) while the same configuration's resolutionStrategy calls failOnDynamicVersions() or failOnNonReproducibleResolution().
Common situations: Teams adopting dependency locking on builds that already guarded reproducibility with failOnNonReproducibleResolution(); platform conventions applied globally colliding with per-project locking; CI enabling locking while a convention plugin sets failOnDynamicVersions for release checks.
Related errors
- Both dependency locking and fail on changing versions are en
- Cannot register a factory for type %s because it is not a su
- The Gradle property '<propertyName>' (set to '<systemPropert
- Invalid format: '{}'. The correct notation is a 3-part group
- Invalid format: '{}'. The correct notation is a 3-part group
AI-assisted analysis of gradle/gradle@534f27719b (2026-08-22).
Data as JSON: /api/errors/6dbbc51c9b0c55c7.
Report an issue: GitHub.