{"record":{"id":"6dbbc51c9b0c55c7","repo":"gradle/gradle","slug":"both-dependency-locking-and-fail-on-dynamic-versio","errorCode":null,"errorMessage":"Both dependency locking and fail on dynamic versions are enabled. You must choose between the two modes.","messagePattern":"Both dependency locking and fail on dynamic versions are enabled\\. You must choose between the two modes\\.","errorType":"validation","errorClass":"InvalidUserCodeException","httpStatus":null,"severity":"error","filePath":"platforms/software/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ResolutionExecutor.java","lineNumber":476,"sourceCode":"            repositories,\n            params.getComponentMetadataRules(),\n            params.getVariantDerivationStrategy(),\n            legacyParams.getComponentSelectionRules(),\n            params.isDependencyVerificationEnabled(),\n            params.getCacheExpirationControl(),\n            params.getRootComponent().getMetadata().getAttributesSchema()\n        ));\n\n        return new ComponentResolversChain(resolvers);\n    }\n\n    private ImmutableList<ResolutionParameters.ModuleVersionLock> getAllVersionLocks(ResolutionParameters params) {\n        if (!params.isDependencyLockingEnabled()) {\n            return params.getModuleVersionLocks();\n        }\n\n        if (params.isFailingOnDynamicVersions()) {\n            throw new InvalidUserCodeException(\n                \"Both dependency locking and fail on dynamic versions are enabled. You must choose between the two modes.\"\n            );\n        } else if (params.isFailingOnChangingVersions()) {\n            throw new InvalidUserCodeException(\n                \"Both dependency locking and fail on changing versions are enabled. You must choose between the two modes.\"\n            );\n        }\n\n        return ImmutableList.<ResolutionParameters.ModuleVersionLock>builder()\n            .addAll(getLockfileLocks(params))\n            .addAll(params.getModuleVersionLocks())\n            .build();\n    }\n\n    private ImmutableList<ResolutionParameters.ModuleVersionLock> getLockfileLocks(ResolutionParameters params) {\n        DependencyLockingState dependencyLockingState = dependencyLockingProvider.loadLockState(\n            params.getDependencyLockingId(),\n            params.getResolutionHost().displayName()","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/software/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ResolutionExecutor.java#L458-L494","documentation":"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.","triggerScenarios":"A configuration has dependency locking active (dependencyLocking { lockThisAndSubConfigurations() } / activateDependencyLocking(), or a gradle.lockfile exists) while the same configuration's resolutionStrategy calls failOnDynamicVersions() or failOnNonReproducibleResolution().","commonSituations":"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.","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"],"exampleFix":"// before\nconfigurations {\n    compileClasspath {\n        resolutionStrategy.failOnNonReproducibleResolution()\n        dependencyLocking { lockThisAndSubConfigurations() }\n    }\n}\n// after\nconfigurations {\n    compileClasspath {\n        dependencyLocking { lockThisAndSubConfigurations() }\n    }\n}","handlingStrategy":"validation","validationCode":"// Convention-plugin guard: do not enable fail-on-dynamic where lockfiles exist\nallprojects {\n    afterEvaluate {\n        def hasLock = file('gradle.lockfile').exists()\n        if (hasLock) {\n            configurations.matching { it.resolutionStrategy }.all { c ->\n                // nothing to enforce directly; keep conventions from setting the flag\n            }\n        }\n    }\n}\n// Prefer: only set failOnDynamicVersions when locking is NOT configured\nif (!project.file('gradle.lockfile').exists()) {\n    configurations.all { resolutionStrategy.failOnNonReproducibleResolution() }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["gradle","dependency-locking","resolution-strategy","conflict","dynamic-versions"],"backgroundTag":"conflicting-resolution-modes","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}