junit-team/junit5 · error · PreconditionViolationException
temp directory must be a directory
Error message
temp directory must be a directory
What it means
Thrown by CloseablePath's constructor when the TempDirFactory.createTempDirectory() returns a Path that is null or does not point to an existing directory (Files.isDirectory is false). The constructor closes the (already-created) factory and throws a PreconditionViolationException, ensuring no half-initialised CloseablePath leaks.
Source
Thrown at junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java:273
static class CloseablePath implements Store.CloseableResource, AutoCloseable {
private final @Nullable Path dir;
private final TempDirFactory factory;
private final Cleanup cleanup;
private final AnnotatedElementContext elementContext;
private final ExtensionContext extensionContext;
private CloseablePath(TempDirFactory factory, Cleanup cleanup, Class<?> elementType,
AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception {
this.dir = factory.createTempDirectory(elementContext, extensionContext);
this.factory = factory;
this.cleanup = cleanup;
this.elementContext = elementContext;
this.extensionContext = extensionContext;
if (this.dir == null || !Files.isDirectory(this.dir)) {
close();
throw new PreconditionViolationException("temp directory must be a directory");
}
if (elementType == File.class && !this.dir.getFileSystem().equals(FileSystems.getDefault())) {
close();
throw new PreconditionViolationException(
"temp directory with non-default file system cannot be injected into " + File.class.getName()
+ " target");
}
}
Path get() {
return requireNonNull(this.dir);
}
@Override
public void close() throws IOException {
try {
if (this.dir != null) {View on GitHub (pinned to 956246301e)
Solutions
- Fix the custom TempDirFactory to always return a non-null Path pointing at an existing directory (use Files.createTempDirectory).
- Never return null from createTempDirectory — create the directory first.
- If the path may be deleted concurrently, create it in a retry loop or under a lock.
Example fix
// before
class MyFactory implements TempDirFactory {
public Path createTempDirectory(AnnotatedElementContext c, ExtensionContext ec) {
return Path.of("/tmp/mydir"); // may not exist or may be a file
}
}
// after
class MyFactory implements TempDirFactory {
public Path createTempDirectory(AnnotatedElementContext c, ExtensionContext ec) throws Exception {
return Files.createTempDirectory("mydir-");
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate a custom factory's output before wiring it
Path p = factory.createTempDirectory(elementContext, extensionContext);
if (p == null || !Files.isDirectory(p)) {
throw new IllegalStateException("Factory must return an existing directory, got: " + p);
} Type guard
static boolean factoryReturnsDirectory(TempDirFactory f, AnnotatedElementContext ec, ExtensionContext ctx) throws Exception {
Path p = f.createTempDirectory(ec, ctx);
return p != null && Files.isDirectory(p);
} Prevention
- Custom TempDirFactory should use Files.createTempDirectory which always returns a real directory.
- Never return null from createTempDirectory.
- Unit-test the factory returns a directory that exists.
When it happens
Trigger: A custom TempDirFactory returns null, returns a path to a regular file, or returns a path that was concurrently deleted before the constructor's isDirectory check. The default factory never triggers this because Files.createTempDirectory always returns a real directory.
Common situations: A custom factory that returns a hardcoded Path.of("/some/path") which is a file or does not exist; a factory that returns null as a sentinel; a race where another process deletes the created directory between creation and validation.
Related errors
- Failed to create default temp directory
- temp directory with non-default file system cannot be inject
- @TempDir field [<field>] must not be declared as final.
- Can only resolve @TempDir <target> of type java.nio.file.Pat
- Failed to copy files to the output directory
AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04).
Data as JSON: /data/errors/5845f25dbb060efd.json.
Report an issue: GitHub.