junit-team/junit5 · error · UncheckedIOException

Failed to copy files to the output directory

Error message

Failed to copy files to the output directory

What it means

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.

Solutions

  1. Ensure the configured report output directory (junit.platform.output.capture.stdout / the report entry output dir) exists and is writable before tests run.
  2. Inspect the wrapped IOException (getCause()) for the precise reason (AccessDeniedException, FileAlreadyExistsException, NoSuchFileException) and resolve it.
  3. If publishing a directory tree, verify the source tree is readable and that no destination entry collides with an existing non-directory file.
  4. Free disk space or widen the temp/report path length limits on Windows.

Example fix

// before
reporter.publishFile(Path.of("/var/locked/out"), "report");
// after
Path out = Path.of("build/junit-reports");
Files.createDirectories(out);
reporter.publishFile(out, "report");
Defensive patterns

Strategy: validation

Validate before calling

Path dir = reportOutputDir();
Files.createDirectories(dir);
if (!Files.isWritable(dir)) throw new IllegalStateException(dir.toString());

Try / catch

try {
    reporter.publishFile(src, name);
} catch (UncheckedIOException e) {
    IOException cause = e.getCause();
    // resolve AccessDenied/FileAlreadyExists/NoSuchFile from cause
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11). Data as JSON: /api/errors/1dfee3b1eef67c37. Report an issue: GitHub.

Appendix: source

Thrown at junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestReporter.java:160

	@API(status = MAINTAINED, since = "5.13.3")
	default void publishDirectory(Path directory) {
		Preconditions.notNull(directory, "directory must not be null");
		Preconditions.condition(Files.exists(directory), () -> "directory must exist: " + directory);
		Preconditions.condition(Files.isDirectory(directory), () -> "path must represent a directory: " + directory);
		publishDirectory(directory.getFileName().toString(), path -> {
			try (Stream<Path> stream = Files.walk(directory)) {
				stream.forEach(source -> {
					Path destination = path.resolve(directory.relativize(source));
					try {
						if (Files.isDirectory(source)) {
							Files.createDirectories(destination);
						}
						else {
							Files.copy(source, destination, REPLACE_EXISTING);
						}
					}
					catch (IOException e) {
						throw new UncheckedIOException("Failed to copy files to the output directory", e);
					}
				});
			}
		});
	}

	/**
	 * Publish a file with the supplied name and media type written by the supplied
	 * action and attach it to the current test or container.
	 *
	 * <p>The {@link Path} passed to the supplied action will be relative to the
	 * report output directory, but it is up to the action to write the file.
	 *
	 * @param name the name of the file to be published; never {@code null} or
	 * blank and must not contain any path separators
	 * @param mediaType the media type of the file; never {@code null}; use
	 * {@link org.junit.jupiter.api.extension.MediaType#APPLICATION_OCTET_STREAM}
	 * if unknown

View on GitHub (pinned to f070c699a0)