junit-team/junit5 · error · UncheckedIOException

Failed to create output dir

Error message

Failed to create output dir

What it means

Thrown by OutputDir.create() as an UncheckedIOException when createSafely() hits an IOException creating the output directory. OutputDir resolves a directory from OUTPUT_DIR_PROPERTY_NAME (or defaults to target/build/cwd) and calls Files.createDirectories; any I/O failure (permissions, invalid path, read-only filesystem) is wrapped.

Source

Thrown at junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/OutputDir.java:46

import org.apiguardian.api.API;
import org.junit.platform.commons.util.StringUtils;

@API(status = INTERNAL, since = "1.9")
public class OutputDir {

	private static final Pattern OUTPUT_DIR_UNIQUE_NUMBER_PLACEHOLDER_PATTERN = Pattern.compile(
		Pattern.quote(OUTPUT_DIR_UNIQUE_NUMBER_PLACEHOLDER));

	public static OutputDir create(Optional<String> customDir) {
		return create(customDir, () -> Path.of("."));
	}

	static OutputDir create(Optional<String> customDir, Supplier<Path> currentWorkingDir) {
		try {
			return createSafely(customDir, currentWorkingDir);
		}
		catch (IOException e) {
			throw new UncheckedIOException("Failed to create output dir", e);
		}
	}

	/**
	 * Package private for testing purposes.
	 */
	static OutputDir createSafely(Optional<String> customDir, Supplier<Path> currentWorkingDir) throws IOException {
		return createSafely(customDir, currentWorkingDir, new SecureRandom());
	}

	private static OutputDir createSafely(Optional<String> customDir, Supplier<Path> currentWorkingDir,
			SecureRandom random) throws IOException {
		Path cwd = currentWorkingDir.get().toAbsolutePath();
		Path outputDir;

		if (customDir.isPresent() && StringUtils.isNotBlank(customDir.get())) {
			outputDir = cwd.resolve(expandPlaceholders(customDir.get(), random));
		}

View on GitHub (pinned to 956246301e)

Solutions

  1. Set junit.platform.output.dir (OUTPUT_DIR_PROPERTY_NAME) to a writable, valid path.
  2. Ensure the working directory is writable, or run from the project root where target/build can be created.
  3. Check filesystem permissions and free space on the CI agent.
  4. Avoid using unique-number placeholders that expand into illegal path segments.

Example fix

# before
junit.platform.output.dir = /opt/readonly/reports

# after
junit.platform.output.dir = build/test-reports
Defensive patterns

Strategy: try-catch

Validate before calling

Path dir = Path.of(Optional.ofNullable(System.getProperty("junit.platform.output.dir")).orElse("target"));
Files.createDirectories(dir);
if (!Files.isWritable(dir)) throw new IllegalStateException("output dir not writable: " + dir);

Type guard

static boolean isOutputDirWritable(String path) {
    try { Path p = Path.of(path); Files.createDirectories(p); return Files.isWritable(p); }
    catch (IOException e) { return false; }
}

Try / catch

try {
    OutputDir.create(Optional.of(path));
} catch (UncheckedIOException e) {
    // log, fall back to a known-writable dir, or fail the build
    throw new RuntimeException("Cannot init output dir " + path, e);
}

Prevention

When it happens

Trigger: Setting junit.platform.output.dir to a path that cannot be created, or running in a sandbox/container where the default target/ or build/ is not writable. Files.createDirectories throws IOException, caught at OutputDir.create line 45-46.

Common situations: CI runner with a read-only working directory. Misconfigured output dir with illegal characters or pointing at a file. Disk full or quota exceeded. Output dir on a network mount that fails metadata operations.

Related errors


AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04). Data as JSON: /data/errors/b977c81272ff19b8.json. Report an issue: GitHub.