{"record":{"id":"1dfee3b1eef67c37","repo":"junit-team/junit5","slug":"failed-to-copy-files-to-the-output-directory","errorCode":null,"errorMessage":"Failed to copy files to the output directory","messagePattern":"Failed to copy files to the output directory","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestReporter.java","lineNumber":160,"sourceCode":"\t@API(status = MAINTAINED, since = \"5.13.3\")\n\tdefault void publishDirectory(Path directory) {\n\t\tPreconditions.notNull(directory, \"directory must not be null\");\n\t\tPreconditions.condition(Files.exists(directory), () -> \"directory must exist: \" + directory);\n\t\tPreconditions.condition(Files.isDirectory(directory), () -> \"path must represent a directory: \" + directory);\n\t\tpublishDirectory(directory.getFileName().toString(), path -> {\n\t\t\ttry (Stream<Path> stream = Files.walk(directory)) {\n\t\t\t\tstream.forEach(source -> {\n\t\t\t\t\tPath destination = path.resolve(directory.relativize(source));\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (Files.isDirectory(source)) {\n\t\t\t\t\t\t\tFiles.createDirectories(destination);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tFiles.copy(source, destination, REPLACE_EXISTING);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcatch (IOException e) {\n\t\t\t\t\t\tthrow new UncheckedIOException(\"Failed to copy files to the output directory\", e);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Publish a file with the supplied name and media type written by the supplied\n\t * action and attach it to the current test or container.\n\t *\n\t * <p>The {@link Path} passed to the supplied action will be relative to the\n\t * report output directory, but it is up to the action to write the file.\n\t *\n\t * @param name the name of the file to be published; never {@code null} or\n\t * blank and must not contain any path separators\n\t * @param mediaType the media type of the file; never {@code null}; use\n\t * {@link org.junit.jupiter.api.extension.MediaType#APPLICATION_OCTET_STREAM}\n\t * if unknown","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestReporter.java#L142-L178","documentation":"Wrapped UncheckedIOException thrown inside TestReporter.publishFile(...) when Files.createDirectories or Files.copy fails while copying a published file to the report output directory. It surfaces I/O errors from the file-publishing helper as a runtime exception so the test extension pipeline can propagate them.","triggerScenarios":"Calling TestReporter.publishFile(...) (the variant that copies an existing directory tree into the report output dir) when the destination path cannot be created or a source file cannot be copied — e.g. permission denied, path collision with a non-directory, read-only mount, or a missing parent.","commonSituations":"Report output directory pointing at a read-only or non-existent location without creation rights; publishing a large attachment when the disk is full; a path that already exists as a regular file where a directory is expected; CI runners with restricted working directories.","solutions":["Ensure the configured report output directory (junit.platform.output.capture.stdout / the report entry output dir) exists and is writable before tests run.","Inspect the wrapped IOException (getCause()) for the precise reason (AccessDeniedException, FileAlreadyExistsException, NoSuchFileException) and resolve it.","If publishing a directory tree, verify the source tree is readable and that no destination entry collides with an existing non-directory file.","Free disk space or widen the temp/report path length limits on Windows."],"exampleFix":"// before\nreporter.publishFile(Path.of(\"/var/locked/out\"), \"report\");\n// after\nPath out = Path.of(\"build/junit-reports\");\nFiles.createDirectories(out);\nreporter.publishFile(out, \"report\");","handlingStrategy":"validation","validationCode":"Path dir = reportOutputDir();\nFiles.createDirectories(dir);\nif (!Files.isWritable(dir)) throw new IllegalStateException(dir.toString());","typeGuard":null,"tryCatchPattern":"try {\n    reporter.publishFile(src, name);\n} catch (UncheckedIOException e) {\n    IOException cause = e.getCause();\n    // resolve AccessDenied/FileAlreadyExists/NoSuchFile from cause\n}","preventionTips":["Pre-create and verify writability of the report output directory.","Avoid publishing into read-only or shared mounts.","Read the wrapped IOException for the true filesystem reason."],"tags":["io","test-reporter","unchecked-io-exception","attachments","filesystem"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}