Gradle-License-Report icon indicating copy to clipboard operation
Gradle-License-Report copied to clipboard

`./gradlew generateLicenseReport --stacktrace` fails with NPE

Open bric3 opened this issue 1 year ago • 11 comments

On multi-module projects, the generation task fails with an NPE

------------------------------------------------------------
Gradle 8.8
------------------------------------------------------------

Build time:   2024-05-31 21:46:56 UTC
Revision:     4bd1b3d3fc3f31db5a26eecb416a165b8cc36082

Kotlin:       1.9.22
Groovy:       3.0.21
Ant:          Apache Ant(TM) version 1.10.13 compiled on January 4 2023
JVM:          21.0.2 (Amazon.com Inc. 21.0.2+13-LTS)
OS:           Mac OS X 14.5 aarch64
Caused by: java.lang.NullPointerException: Cannot get property 'configurations' on null object
	at com.github.jk1.license.reader.ProjectReader.findConfiguredConfigurations(ProjectReader.groovy:96)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at com.github.jk1.license.reader.ProjectReader.findConfigurationsToScan(ProjectReader.groovy:71)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at com.github.jk1.license.task.ReportTask$_getClasspath_closure1.doCall$original(ReportTask.groovy:51)
	at com.github.jk1.license.task.ReportTask$_getClasspath_closure1.doCall(ReportTask.groovy)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at com.github.jk1.license.task.ReportTask.getClasspath(ReportTask.groovy:50)
	at com.github.jk1.license.task.ReportTask_Decorated.getClasspath(Unknown Source)

I don't understand yet the conditions why this is failing, but for sure the project is null

image

this seems to come from the ReportTasks image

But the extension is supposed to have the current project and sub-projects

https://github.com/jk1/Gradle-License-Report/blob/a420142e94307b3817023c6914ae6ed512ce3915/src/main/groovy/com/github/jk1/license/LicenseReportExtension.groovy#L48

The getClasspath method is called on the ReportTask that was configured on my root project.

image
Full stacktrace
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':generateLicenseReport'.
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314)
	at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
Caused by: org.gradle.api.internal.tasks.properties.PropertyEvaluationException: Error while evaluating property 'classpath' of task ':generateLicenseReport'.
	at org.gradle.api.internal.tasks.properties.InputParameterUtils.prepareInputParameterValue(InputParameterUtils.java:32)
	at org.gradle.api.internal.tasks.execution.TaskExecution.lambda$visitRegularInputs$1(TaskExecution.java:317)
	at org.gradle.internal.execution.impl.DefaultInputFingerprinter$InputCollectingVisitor.visitInputProperty(DefaultInputFingerprinter.java:103)
	at org.gradle.api.internal.tasks.execution.TaskExecution.visitRegularInputs(TaskExecution.java:315)
	at org.gradle.internal.execution.impl.DefaultInputFingerprinter.fingerprintInputProperties(DefaultInputFingerprinter.java:63)
	at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.captureExecutionStateWithOutputs(AbstractCaptureStateBeforeExecutionStep.java:109)
	at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.lambda$captureExecutionState$0(AbstractCaptureStateBeforeExecutionStep.java:74)
	at org.gradle.internal.execution.steps.BuildOperationStep$1.call(BuildOperationStep.java:37)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.internal.execution.steps.BuildOperationStep.operation(BuildOperationStep.java:34)
	at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.captureExecutionState(AbstractCaptureStateBeforeExecutionStep.java:69)
	at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:62)
	at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:43)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.executeWithNonEmptySources(AbstractSkipEmptyWorkStep.java:125)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:56)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:36)
	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
	at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:36)
	at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:23)
	at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:75)
	at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:41)
	at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.lambda$execute$0(AssignMutableWorkspaceStep.java:35)
	at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:289)
	at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:31)
	at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:22)
	at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:40)
	at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:23)
	at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.lambda$execute$2(ExecuteWorkBuildOperationFiringStep.java:67)
	at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:67)
	at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:39)
	at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:46)
	at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:34)
	at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:48)
	at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:35)
	at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:61)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:127)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:116)
	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
	at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314)
	at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
Caused by: java.lang.NullPointerException: Cannot get property 'configurations' on null object
	at com.github.jk1.license.reader.ProjectReader.findConfiguredConfigurations(ProjectReader.groovy:96)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at com.github.jk1.license.reader.ProjectReader.findConfigurationsToScan(ProjectReader.groovy:71)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at com.github.jk1.license.task.ReportTask$_getClasspath_closure1.doCall$original(ReportTask.groovy:51)
	at com.github.jk1.license.task.ReportTask$_getClasspath_closure1.doCall(ReportTask.groovy)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at com.github.jk1.license.task.ReportTask.getClasspath(ReportTask.groovy:50)
	at com.github.jk1.license.task.ReportTask_Decorated.getClasspath(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at org.gradle.internal.reflect.annotations.impl.DefaultPropertyAnnotationMetadata.getPropertyValue(DefaultPropertyAnnotationMetadata.java:97)
	at org.gradle.internal.properties.annotations.DefaultTypeMetadataStore$DefaultPropertyMetadata.getPropertyValue(DefaultTypeMetadataStore.java:284)
	at org.gradle.internal.properties.bean.DefaultPropertyWalker$1.lambda$visitLeaf$0(DefaultPropertyWalker.java:90)
	at org.gradle.internal.deprecation.DeprecationLogger.whileDisabled(DeprecationLogger.java:253)
	at org.gradle.internal.properties.bean.DefaultPropertyWalker$CachedPropertyValue.lambda$new$0(DefaultPropertyWalker.java:107)
	at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:181)
	at org.gradle.internal.properties.bean.DefaultPropertyWalker$CachedPropertyValue.call(DefaultPropertyWalker.java:149)
	at org.gradle.util.internal.GUtil.uncheckedCall(GUtil.java:437)
	at org.gradle.util.internal.DeferredUtil.unpackNestableDeferred(DeferredUtil.java:83)
	at org.gradle.util.internal.DeferredUtil.unpack(DeferredUtil.java:57)
	at org.gradle.util.internal.DeferredUtil.unpackOrNull(DeferredUtil.java:49)
	at org.gradle.api.internal.tasks.properties.InputParameterUtils.prepareInputParameterValue(InputParameterUtils.java:38)
	at org.gradle.api.internal.tasks.properties.InputParameterUtils.prepareInputParameterValue(InputParameterUtils.java:30)
	... 69 more

bric3 avatar Jun 20 '24 13:06 bric3

Even explicitly configuring the projects in the parent project doesn't help

extensions.configure<LicenseReportExtension> {
    projects = (subprojects - project(":modules")).toTypedArray()
    // projects = arrayOf(
    //     project(":modules:jvm"),
    //     project(":modules:go"),
    //     project(":modules:js"),
    //     project(":modules:php"),
    //     project(":modules:python"),
    //     project(":modules:ruby"),
    // )
}

bric3 avatar Jun 20 '24 14:06 bric3

I guess you need to provide an MCVE, because for me it works fine on a multi-module project, so there has to be some edge-case you are hitting.

Vampire avatar Jul 30 '24 21:07 Vampire

Also in your last screenshot you are looking at the wrong field. You are looking at project of Task. You have to look at projects in config which for you is a 1-sized array containing only a null entry.

Vampire avatar Aug 29 '24 20:08 Vampire

Sorry I put aside this issue for a couple of months, I'll take a fresher look, there have been quite changes since then in the build file.

bric3 avatar Aug 30 '24 10:08 bric3

OK I don't know if the message were back then (Gradle 8.8) — I would assume they were — so I feel pretty stupid, the build is failing with these messages now (Gradle 8.10) :

2 problems were found storing the configuration cache.
- Task `:generateLicenseReport` of type `com.github.jk1.license.task.ReportTask`: cannot deserialize object of type 'org.gradle.api.Project' as these are not supported with the configuration cache.
  See https://docs.gradle.org/8.10/userguide/configuration_cache.html#config_cache:requirements:disallowed_types
- Task `:generateLicenseReport` of type `com.github.jk1.license.task.ReportTask`: cannot serialize object of type 'org.gradle.api.internal.project.LifecycleAwareProject', a subtype of 'org.gradle.api.Project', as these are not supported with the configuration cache.
  See https://docs.gradle.org/8.10/userguide/configuration_cache.html#config_cache:requirements:disallowed_types

See the complete report at file:///Users/brice.dutheil/go/src/github.com/DataDog/datadog-intellij-plugin/build/reports/configuration-cache/9npi88kle0xljc5ipkr6p3pr3/5zyu60caq1c85gip0dv3e8wud/configuration-cache-report.html

And indeed I have the gradle configuration cache enabled by default in the gradle properties file:

org.gradle.configuration-cache=true

Turning it off made the task work

 ./gradlew generateLicenseReport -Dorg.gradle.configuration-cache=false

bric3 avatar Aug 30 '24 13:08 bric3

@Vampire That said I'm not sure this task can be used from an existing build without disabling the configuration cache. E.g. something like this

tasks {
    register("assemble") {
        dependsOn(generateLicenseReport)
    }
}

extensions.configure<LicenseReportExtension> {
    projects = subprojects.toTypedArray()
}

Note I'm using

  • Gradle 8.10
  • com.github.jk1.dependency-license-report 2.8

I've seen some work started since #255, #269.

bric3 avatar Aug 30 '24 13:08 bric3

Yeah, CC will cause that to be null indeed, so I'd say this is a duplicate of CC incompatible issue. You can probably mark the task as not compatible for the moment to not use CC if the task is executed in the same run

Vampire avatar Aug 30 '24 16:08 Vampire

I don't think notCompatibleWithConfigurationCache("Unsupported") can work entirely (I coudn't) because the build is complaining about the project which is an input to the task especially when the warning mode is enabled in the properties.

org.gradle.configuration-cache.problems=warn
tasks.withType<ReportTask>().configureEach {
    notCompatibleWithConfigurationCache("Unsupported")
}

Seems related to https://github.com/gradle/gradle/issues/20673

bric3 avatar Aug 30 '24 22:08 bric3

Ah right, the CC state is always serialized and then deserialized and used, even with that option set, it is just not persisted. So yeah, makes senes that it still fails.

Vampire avatar Aug 30 '24 23:08 Vampire

To fix this, the task input would have to be configured to not take in the project object for use during execution time. You could create a new class that could contain the info you need, like configuration, project name, etc. to potentially avoid this. Just went through this exercise in one of our internal plugins for work. Not too bad to do, but does take some effort to get into compliance with the configuration-cache spec.

Dravarix avatar Oct 25 '24 19:10 Dravarix

Yes, as I said, this is a duplicate of the CC incompatibility issue. :-)

Vampire avatar Oct 26 '24 12:10 Vampire