Philip W
08/05/2026, 7:29 AMVampire
08/05/2026, 7:48 AMPhilip W
08/05/2026, 7:52 AMVampire
08/05/2026, 8:14 AMPhilip W
08/05/2026, 8:20 AMVampire
08/05/2026, 8:45 AMHow can it be a bug on my side?Well, whoever captures the script reference. So probably not in the plugin, no. But if you for example then set a property to some provider that references the script instance, you get that problem. Really hard to talk about in theory, that's why I asked for an MCVE that shows the problem. 🙂
But anyway, reusing the same Definition classes for all layers (DSL, BuildModel, Task, Action) looks like to a code smell to me.Well, if that is your stand, then the question is no question anymore, is it? 😄
Philip W
08/05/2026, 9:09 AMabstract class MyTask : DefaultTask() {
@get:Inject
abstract val workerExecutor: WorkerExecutor
@TaskAction
fun action() {
workerExecutor.classLoaderIsolation {
}.submit(MyWorkAction::class.java) {
}
}
}
abstract class MyWorkAction : WorkAction<MyWorkActionParameters> {
override fun execute() {
}
}
interface MyWorkActionParameters : WorkParameters {
val myNDOC: NamedDomainObjectContainer<Foo>
}
interface Foo : Named
tasks.register("myTask", MyTask::class)
Cause: class java.util.LinkedHashSet cannot be cast to class org.gradle.api.NamedDomainObjectContainer (java.util.LinkedHashSet is in module java.base of loader 'bootstrap'; org.gradle.api.NamedDomainObjectContainer is in unnamed module of loader 'app')Philip W
08/05/2026, 9:11 AMPhilip W
08/05/2026, 9:16 AMabstract class MyTask : DefaultTask() {
@get:Inject
abstract val workerExecutor: WorkerExecutor
@get:Input
abstract val myNDOC: NamedDomainObjectContainer<Foo>
@get:Inject
abstract val objectFactory: ObjectFactory
@TaskAction
protected fun action() {
println("Task: " + myNDOC.joinToString { it.name })
workerExecutor.classLoaderIsolation {
}.submit(MyWorkAction::class.java) {
myNDOC.addAll(this@MyTask.myNDOC.map {
objectFactory.newInstance<Foo>(it.name)
})
}
}
}
abstract class MyWorkAction : WorkAction<MyWorkActionParameters> {
override fun execute() {
println("Action: " + parameters.myNDOC.get().joinToString { it.name })
}
}
interface MyWorkActionParameters : WorkParameters {
val myNDOC: SetProperty<Foo>
}
interface Foo : Named {
@Input
override fun getName(): String
}
tasks.register("myTask", MyTask::class) {
myNDOC.create("asf")
}Vampire
08/05/2026, 9:28 AMCause: class java.util.LinkedHashSet cannot be cast to class org.gradle.api.NamedDomainObjectContainerThat is neither a build script reference error, nor is it a CC error. This fails even with CC switched off. This imho is either way a Gradle bug. Either it should support
NamedDomainObjectContainer at that place or give a clear error,
instead of serializing it to a LinkedHashSet and then fail with ClassCastException on deserialization.
So Gradle should either support it or throw a clear and actionable error.
And you also need to annotate all your DSL types with Input, Output and so on,Yes, but that might not be a problem as they are just annotations for the case a usage needs them. 🤷♂️
but different tasks could need different inputs/PathSensitive etc.If that is the case, then you should probably on task level not use it but on task level wire exactly what you need to properties annotated like you need it for that task.
And using a SetProperty shows this bug:Not sure what you mean, it runs successfully. If I add an output so that fingerprinting happens, then you get an error that NDOC is not serializable, but that is expected. NDOC is not serializable, you probably wanted
@Nested and with that it works
Task ':myTask' is not up-to-date because:
Input property 'myNDOC.asf1353989242$0' has been removed for task ':myTask'
Input property 'myNDOC.asf1353989242$0.name' has been removed for task ':myTask'
Input property 'myNDOC.asf-173265204$0' has been added for task ':myTask'
and more...Philip W
08/05/2026, 9:31 AMPhilip W
08/05/2026, 9:34 AMNot sure what you mean, it runs successfully.Whats your output?
Vampire
08/05/2026, 9:34 AMPhilip W
08/05/2026, 9:35 AMVampire
08/05/2026, 9:36 AMPhilip W
08/05/2026, 9:36 AMPhilip W
08/05/2026, 9:38 AMVampire
08/05/2026, 9:38 AMVampire
08/05/2026, 9:42 AMgetName override and make the Nested Internal instead,
you get an NPE from Kotlin because getName returned null which violated its contract.
You just seem to have weakened that somehow, or the name is not null but "null". 😕Philip W
08/05/2026, 9:43 AMVampire
08/05/2026, 9:44 AMnull which the JavaDoc of getName states must never happen.
I really wonder now why it outputs Action: null instead of throwing NPE from Kotlin already.Vampire
08/05/2026, 9:48 AMVampire
08/05/2026, 9:55 AMPhilip W
08/05/2026, 10:10 AMVampire
08/07/2026, 2:08 PM