'tasks' task fails if rules mutation occurs later

We’re having trouble with the tasks task failing with a particular combination of build/publish task dependencies that causes org.gradle.api.publish.ivy.plugins.IvyPublishPlugin.Rules#createTasks to not happen when the tasks task is run, and means that the task graph can’t be evaluated when tasks is run:

Caused by: org.gradle.api.UnknownTaskException: Task with path 'generateDescriptorFileForNebulaIvyPublication' not found in project ':dir:sub1'.
    at org.gradle.api.internal.tasks.DefaultTaskContainer.getByPath(DefaultTaskContainer.java:164)
    at org.gradle.api.internal.tasks.DefaultTaskContainer.resolveTask(DefaultTaskContainer.java:158)
    at org.gradle.api.internal.tasks.DefaultTaskDependency.visitDependencies(DefaultTaskDependency.java:85)
    at org.gradle.api.internal.tasks.CachingTaskDependencyResolveContext$TaskGraphImpl.getNodeValues(CachingTaskDependencyResolveContext.java:88)
    at org.gradle.internal.graph.CachingDirectedGraphWalker$GraphWithEmpyEdges.getNodeValues(CachingDirectedGraphWalker.java:202)
    at org.gradle.internal.graph.CachingDirectedGraphWalker.doSearch(CachingDirectedGraphWalker.java:112)
    at org.gradle.internal.graph.CachingDirectedGraphWalker.findValues(CachingDirectedGraphWalker.java:64)
    at org.gradle.api.internal.tasks.CachingTaskDependencyResolveContext.doResolve(CachingTaskDependencyResolveContext.java:76)
    at org.gradle.api.internal.tasks.CachingTaskDependencyResolveContext.resolve(CachingTaskDependencyResolveContext.java:65)
    ... 77 more

Due to the complexity, I’m having trouble creating a reduced test case to demonstrate the issue, but it feels like a bug to me so hoping that one of the Gradle folks will see this description and be able to know what’s going on.

I ran into this today and for me the cause was I was using tasks.withType(SomeType) {} in my mutate function. tasks.withType(), just like tasks.all() operate not only on existing tasks, but also on any tasks added later. While the types of task I was operating on didn’t seem like they should cause this problem, and I don’t know why the task creation order is different when running “tasks”, changing my code to use tasks.findAll {criteria}.each {} removed the problem, as it doesn’t apply the closure on future tasks.