{"record":{"id":"11f3c5649b99f535","repo":"junit-team/junit5","slug":"failed-to-write-report","errorCode":null,"errorMessage":"Failed to write report","messagePattern":"Failed to write report","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java","lineNumber":79,"sourceCode":"\t\t\tvar apiReport = generateReport(scanResult);\n\n\t\t\t// ApiReportWriter reportWriter = new MarkdownApiReportWriter(apiReport);\n\t\t\tApiReportWriter reportWriter = new AsciidocApiReportWriter(apiReport);\n\t\t\t// ApiReportWriter reportWriter = new HtmlApiReportWriter(apiReport);\n\n\t\t\t// reportWriter.printReportHeader(new PrintWriter(System.out, true));\n\n\t\t\t// Print report for all Usage enum constants\n\t\t\t// reportWriter.printDeclarationInfo(new PrintWriter(System.out, true), EnumSet.allOf(Status.class));\n\n\t\t\t// Print report only for specific Status constants, defaults to only EXPERIMENTAL\n\t\t\tparseArgs(args).forEach((status, opener) -> {\n\t\t\t\ttry (var stream = opener.openStream()) {\n\t\t\t\t\tvar writer = new PrintWriter(stream == null ? System.out : stream, true, UTF_8);\n\t\t\t\t\treportWriter.printDeclarationInfo(writer, EnumSet.of(status));\n\t\t\t\t}\n\t\t\t\tcatch (IOException e) {\n\t\t\t\t\tthrow new UncheckedIOException(\"Failed to write report\", e);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t// -------------------------------------------------------------------------\n\n\tprivate static Map<Status, StreamOpener> parseArgs(String[] args) {\n\t\tMap<Status, StreamOpener> outputByStatus = new EnumMap<>(Status.class);\n\t\tif (args.length == 0) {\n\t\t\toutputByStatus.put(Status.EXPERIMENTAL, () -> null);\n\t\t}\n\t\telse {\n\t\t\tArrays.stream(args) //\n\t\t\t\t\t.map(arg -> arg.split(\"=\", 2)) //\n\t\t\t\t\t.forEach(parts -> outputByStatus.put(//\n\t\t\t\t\t\tStatus.valueOf(parts[0]), //\n\t\t\t\t\t\t() -> parts.length < 2 //","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java#L61-L97","documentation":"Thrown by the internal ApiReportGenerator tool (used to produce the JUnit API status report) when an I/O error occurs while writing the generated report to its output stream. It wraps the underlying IOException in an UncheckedIOException so the forEach lambda can propagate a checked exception. This is build/tooling code, not part of the public test API.","triggerScenarios":"Running the ApiReportGenerator main entry with an output target whose StreamOpener.openStream() fails (e.g. the stream's writer throws IOException mid-write), or the destination is unwritable/closed. The catch in the try-with-resources around the opener.openStream()/PrintWriter write path converts any IOException to this UncheckedIOException.","commonSituations":"Pointing the report at a directory that doesn't exist or lacks write permission; a closed/already-consumed stream returned by a custom StreamOpener; running the tool from a sandbox with restricted filesystem access; disk-full or path-too-long during large report writes.","solutions":["Check that the output path/directory the generator is asked to write to exists and is writable before running the tool.","If you passed a custom StreamOpener, ensure openStream() returns a fresh, open, writable stream and that no prior consumer closed it.","Read the wrapped IOException (getCause()) for the real filesystem reason (permission, ENOSPC, not-a-directory) and address that directly.","Run the generator with explicit/redirected output or the default EXPERIMENTAL target (no args) to isolate whether the failure is path-specific."],"exampleFix":"// before: opener points at an unwritable path\n@ParameterizedTest\n...\n// after: preflight the destination\nPath out = Path.of(\"build/api-report\");\nFiles.createDirectories(out);\nif (!Files.isWritable(out)) {\n    throw new IllegalStateException(\"Report dir not writable: \" + out);\n}","handlingStrategy":"validation","validationCode":"Path out = resolveOutputPath();\nFiles.createDirectories(out);\nif (!Files.isWritable(out)) {\n    throw new IllegalStateException(\"Output not writable: \" + out);\n}","typeGuard":null,"tryCatchPattern":"try {\n    generator.run(args);\n} catch (UncheckedIOException e) {\n    IOException cause = e.getCause();\n    // handle filesystem-level cause (permission, ENOSPC, closed stream)\n}","preventionTips":["Validate the output destination is writable before invoking the generator.","Return fresh, open streams from any custom StreamOpener.","Treat the wrapped IOException as the source of truth for the real failure."],"tags":["io","tooling","unchecked-io-exception","report-generation","junit-internal"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}