gradle/gradle · error · GenericHtmlReportGenerationException

Could not generate test report to '%s'.

Error message

Could not generate test report to '%s'.

What it means

GenericHtmlTestReportGenerator.generateFiles wraps the whole generic HTML report generation in a try/catch and rethrows any Exception as GenericHtmlReportGenerationException formatted with the reports directory. It is an umbrella: the actionable failure is always the wrapped cause, ranging from path-length limits to I/O errors to report-model invariant violations.

Source

Thrown at platforms/software/testing-base/src/main/java/org/gradle/api/internal/tasks/testing/report/generic/GenericHtmlTestReportGenerator.java:190

                            if (childTree.hasUsefulDetails()) {
                                requestsBuilder.add(childTree);
                            }
                        } else {
                            queueTree(queue, childTree, output);
                        }
                    }
                    // This is mostly I/O, so run it unconstrained to allow more parallelism
                    queue.addUnconstrained(new HtmlReportFileGenerator(
                        shrink,
                        requestsBuilder.build(),
                        output,
                        outputReaders,
                        rootDisplayNames
                    ));
                }
            }, reportsDirectory.toFile());
        } catch (Exception e) {
            throw new GenericHtmlReportGenerationException(String.format("Could not generate test report to '%s'.", reportsDirectory), e);
        }
    }

    private static String getDisplayName(TestTreeModel model, int rootIndex) {
        List<PerRootInfo> perRootInfos = model.getPerRootInfo().get(rootIndex);
        if (perRootInfos.isEmpty()) {
            throw new IllegalStateException("Root model is missing display name info for root index " + rootIndex);
        }
        if (perRootInfos.size() > 1) {
            throw new IllegalStateException("Root model has multiple display name infos for root index " + rootIndex + ": " + Iterables.toString(perRootInfos));
        }
        return SerializableTestResult.getCombinedDisplayName(perRootInfos.get(0).getResults());
    }

    private static final class HtmlReportFileGenerator implements RunnableBuildOperation {
        private final boolean shrink;
        private final List<TestTreeModel> requests;
        private final HtmlReportBuilder output;

View on GitHub (pinned to 534f27719b)

Solutions

  1. Unwrap and read getCause() — fix the specific nested exception (UnshrinkableReportPathException, IOException, invariant error) rather than the umbrella message
  2. Delete build/reports/tests and build/test-results and re-run to eliminate corrupt leftovers from an aborted run
  3. If the cause is the unshrinkable path: shorten the report directory, reduce test nesting/names, or set reports.html.required = false
  4. Check disk space and permissions/locks (antivirus on Windows) on the reports directory

Example fix

// build.gradle.kts — stop HTML report generation from failing the build when it is not needed
tasks.withType<Test>().configureEach {
    reports.html.required.set(false)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before enabling HTML reports, sanity-check the target directory
File reportsDir = testTask.getReports().getHtml().getOutputLocation().getAsFile().get();
if (!reportsDir.exists() ? !reportsDir.mkdirs() : !reportsDir.isDirectory() || !reportsDir.canWrite()) {
    throw new InvalidUserDataException("Cannot write test report to " + reportsDir);
}

Try / catch

try { run test task } catch (GenericHtmlReportGenerationException e) { Throwable cause = e.getCause(); if (cause instanceof UnshrinkableReportPathException) { disable/shorten report } else { rethrow or fail with cause } } — always branch on the nested cause, never the umbrella message.

Prevention

When it happens

Trigger: Nested UnshrinkableReportPathException when a report file path cannot fit the limit; IOException while deleting the old report or writing files into the reports directory; IllegalStateException from report model invariants (e.g. 'Root model is missing display name info'); failures reading output-events.bin from the result store.

Common situations: Deep build directory paths on Windows hitting path limits; read-only, locked, or full disk at build/reports/tests; leftover corrupt results from a previously killed build; report aggregation setups combining results produced by different Gradle versions.

Related errors


AI-assisted analysis of gradle/gradle@534f27719b (2026-08-22). Data as JSON: /api/errors/7ec19683b9cd88bd. Report an issue: GitHub.