How to fix my task for Gradle 9.0 RC1?

I have this task which works in Gradle 8 but not in Gradle 9:

tasks.register('copyResources') {
    def schemaFile = project(':manualWorker').file('src/main/resources/schema.json')

    doLast {
        copy {  // <-- THIS IS SEEMINGLY THE ISSUE
            from '../../workers/utils/sharedScripts'
            exclude 'dashboard.sh'
            into 'build/deploy'
        }
        copy {
            from schemaFile
            into 'build/deploy'
        }
    }
}

The error I’m getting is:

* What went wrong:
Execution failed for task ':manualWorker:copyResources'.
> Invocation of 'copy' references a Gradle script object from a Groovy closure at execution time, which is unsupported with the configuration cache.

Is there an easy way to fix it? I tried some AI and I read some documentation but I’m still not entirely sure how to fix it myself.

Thank you for any help!

You probably enabled configuration cache or created a new build with Gradle 9 which enabled configuration cache by default.

Even with Gradle 8 your snippet will fail with configuration cache enabled due to you calling project.copy { ... } in the execution phase.

Your task should probably more look something like

tasks.register('copyResources', Sync) {
   from('../../workers/utils/sharedScripts') {
      exclude 'dashboard.sh'
   }
   from project(':manualWorker').file('src/main/resources/schema.json')
   into 'build/deploy'
}

then it can also be properly up-to-date and also eliminate stale files in the target directory.

If you really need the task to always run and not properly track inputs and outputs, it is probably the easiest to create a proper task class into which you inject an instance of FileSystemOperations and use the copy method of that, or use the more hacky

interface FileSystemOperationsProvider {
   @Inject
   FileSystemOperations getFs()
}
tasks.register('copyResources') {
   def schemaFile = file('src/main/resources/schema.json')
   def fs = objects.newInstance(FileSystemOperationsProvider).fs

   doLast {
      fs.copy {  // <-- THIS IS SEEMINGLY THE ISSUE
         from '../../workers/utils/sharedScripts'
         exclude 'dashboard.sh'
         into 'build/deploy'
      }
      fs.copy {
         from schemaFile
         into 'build/deploy'
      }
   }
}

Ah, so I can add Sync to any task that does not really require configuration cache to fix my issues! And improve it later as needed.

Thank you! Much appreciated!

You do not “add Sync to a task”. That declares a task of type Sync. It is like Copy, just that it deletes files it did not copy to the destination so does not leave stale files. The point is, that by using a task of type Sync or Copy, you do not need to call project.copy or project.sync in execution phase, which is your problem.