Help with 'Cannot change dependencies' error

I’m trying to add the following to my build.gradle file:

 jar {
     manifest {
         attributes["Main-Class"] = "${mainClassName}"
         attributes["Class-Path"] = configurations.runtimeClasspath.collect { 'lib/' + it.getName() }.join(' ')
     }
 }

but when I try to build, I get this:

> Failed to notify project evaluation listener.
   > Cannot change dependencies of dependency configuration ':implementation' after it has been included in dependency resolution.
   > Cannot change dependencies of dependency configuration ':implementation' after it has been included in dependency resolution.

The problem seems to be directly related to this line:

        attributes["Class-Path"] = configurations.runtimeClasspath.collect { 'lib/' + it.getName() }.join(' ')

I stripped down my build.gradle file to just the following and I still get the error:

plugins {
    id("io.micronaut.application") version "3.3.2"
}

repositories {
    mavenCentral()
}

def pathInfo = configurations.runtimeClasspath.collect { 'lib/' + it.getName() }.join(' ')
logger.info('pathInfo {}', "${pathInfo}")

I’m fairly new to Gradle, so I’m trying to understand how iterating over the classpath and assigning the result to a variable should have something to do with changing the dependency configuration. There definitely seems to be something with using the Micronaut plugin, but since I don’t fully understand the error, I’m not sure what the real problem might be.

Looking for any insights that anyone might have on this. I’m running Gradle 7.4.2 on Ubuntu 20.04

What’s happening is that the runtimeClasspath configuration is being resolved during Gradle’s evalutation/configuration phase. Once this happens the configuration can no longer be mutated by the build/plugins. In order to defer the resolution of the configuration to Gradle’s task execution phase, update your buildscript to configure the manifest like so:

jar {
    doFirst {
        manifest {
            attributes["Main-Class"] = "${mainClassName}"
            attributes["Class-Path"] = configurations.runtimeClasspath.collect { 'lib/' + it.getName() }.join(' ')
        }
    }
}

When the jar task executes it will first configure the manifest attributes and then it will proceed with the creation of the jar.

1 Like