Fix reports.register() failing with "Cannot call TaskOutputs.file() after task started execution"#1618
Fix reports.register() failing with "Cannot call TaskOutputs.file() after task started execution"#1618
Conversation
… during execution When using reports.register() for lazy report registration, the domain objects are realized at iteration time. Previously, the factory function called (outputs as TaskOutputs).file() which fails if called during task execution. Fix: remove the outputs.file() call from the factory and instead register all required reports' output files via a lazy provider in the init block. The provider is evaluated at task-graph finalization (before execution), not during the task action itself. Also adds a functional test covering the exact scenario from issue #1539: registering multiple reports with register() without explicit required=true. Fixes #1539 Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
reports.register() failing with "Cannot call TaskOutputs.file() after task has started execution"
The previous approach had two bugs caught by CI:
1. ArchUnit violation: outputs.files() without explicit cast caused Kotlin
to infer AbstractTask.getOutputs() return type as TaskOutputsInternal
(internal Gradle API). Fix: cast to org.gradle.api.tasks.TaskOutputs.
2. Lazy items excluded from output tracking: Kotlin's Collection.filter{}
calls Iterable.iterator() which only returns already-realized items.
Items registered with reports.register() stay pending/lazy and are
invisible to iterator(), so the provider returned an empty file list.
Fix: use reports.matching{} (Gradle's API) which realizes pending items
when the resulting collection is iterated.
Also uses an anonymous Callable object instead of a lambda, following the
existing NamedDomainObjectFactory pattern for configuration-cache safety.
Fixes #1539
Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
reports.register() failing with "Cannot call TaskOutputs.file() after task has started execution"|
@copilot See the ci builds results on this, they are failing for a different reason now. There are also a number of warnings that possibly are unrelated but might as well fix those if possible. |
Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
|
@copilot the build doesn't like commit message 'Changes before error encountered' as it does not follow proper convention, can you rebase and fix that to 'fix: ' prefix like others have? |
Bumps and [picomatch](https://github.com/micromatch/picomatch). These dependencies needed to be updated together. Updates `picomatch` from 2.3.1 to 2.3.2 - [Release notes](https://github.com/micromatch/picomatch/releases) - [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md) - [Commits](micromatch/picomatch@2.3.1...2.3.2) Updates `picomatch` from 4.0.3 to 4.0.4 - [Release notes](https://github.com/micromatch/picomatch/releases) - [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md) - [Commits](micromatch/picomatch@2.3.1...2.3.2) --- updated-dependencies: - dependency-name: picomatch dependency-version: 2.3.2 dependency-type: indirect - dependency-name: picomatch dependency-version: 4.0.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
…dificationException
When Gradle serializes the task state for the configuration cache, it
visits the reports container's internal pending map. If any reports were
registered lazily via reports.register(), the serializer encounters
ProviderInternal objects in that map; realizing those providers moves
entries out of the map while the serializer is still iterating it,
causing a ConcurrentModificationException.
Fix: after executing the user's configuration action inside reports{},
call reports.toList() to force-realize every pending item. This empties
the pending map before the configuration-cache serializer ever visits it,
so the ConcurrentModificationException no longer occurs.
Fixes #1539
Co-authored-by: hazendaz <975267+hazendaz@users.noreply.github.com>
Agent-Logs-Url: https://github.com/spotbugs/spotbugs-gradle-plugin/sessions/822233bf-a461-40e9-bda2-fe726b230db6
I investigated the CI failures more carefully and found two issues:
To fix the commit message, you'll need to force-push manually: git fetch origin copilot/check-issue-1539
git checkout copilot/check-issue-1539
git rebase -i HEAD~6 # mark 02d1ca5 as 'reword'
git push --force-with-lease origin copilot/check-issue-1539Or use Squash and merge on GitHub, which will combine all commits under the PR title. |
Using
reports.register("xml")fails at runtime because theNamedDomainObjectFactorywas callingoutputs.file()lazily — the factory is only invoked when the container is first iterated, which happens insidebuildArguments()during task execution, after Gradle has locked task outputs.Changes
Remove
outputs.file()from the factory — domain object creation no longer has any side-effects on task outputs, makingregister()safe at any point in the lifecycle.Re-register outputs lazily via
reports.matching { }— replaces the removed call with aConfigurableFileCollectionbacked by an anonymousCallable:(outputs as org.gradle.api.tasks.TaskOutputs)explicit cast — without it Kotlin resolvesAbstractTask.getOutputs()to the internalTaskOutputsInternal, which violates the ArchUnit "no Gradle internal API" rule.reports.matching { }(Gradle's API) rather thanreports.filter { }(Kotlin'sIterable.filter) —filteronly iterates already-realized items and silently skips items registered withregister(), causing those reports to be omitted from output tracking.matchingrealizes pending items on iteration.Callableobject rather than a lambda, following the existingNamedDomainObjectFactorypattern for configuration-cache serialization safety.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
dl.google.com/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED -Xmx4g -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-8.14.4-bin/92wwslzcyst3phie3o264zltu/gradle-8.14.4/lib/gradle-daemon-main-8.14.4.jar(dns block)If you need me to access, download, or install something from one of these locations, you can either:
🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.