junit-team/junit5 · error · PreconditionViolationException
Failed to retrieve canonical path for directory
Error message
Failed to retrieve canonical path for directory: ${directory} What it means
DiscoverySelectors.selectDirectory(File) validates non-null and isDirectory(), then calls directory.getCanonicalPath(). If canonical-path resolution throws IOException, a PreconditionViolationException wraps it. Symmetric to the file variant (116).
Solutions
- Ensure read+execute permission on all parent directories so canonicalization can traverse them.
- Fix or remove broken symlinks in the path.
- Prefer selectDirectory(String) with a known absolute canonical path to avoid the getCanonicalPath() call.
- Move the target to a location with straightforward path resolution.
Example fix
// before
DirectorySelector s = selectDirectory(new File("/opt/app/../../etc/tests")); // complex/blocked parents
// after
DirectorySelector s = selectDirectory("/etc/tests"); // absolute canonical path via the String overload Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate that directory canonicalization will succeed.
import java.io.File;
File d = userDir;
if (!d.isDirectory()) throw new IllegalArgumentException("Not an existing directory: " + d);
try { d.getCanonicalPath(); } catch (IOException e) {
throw new IllegalArgumentException("Cannot canonicalize " + d + ": " + e.getMessage(), e);
}
// If at risk, prefer selectDirectory(absoluteCanonicalPathString).
Try / catch
try { return selectDirectory(dir); } catch (PreconditionViolationException e) { return selectDirectory(dir.getAbsolutePath()); } Prevention
- Ensure the test JVM can read+traverse all parent directories of the target directory.
- Prefer selectDirectory(String) with a known absolute canonical path when canonicalization is at risk.
- Avoid broken symlinks in the path chain.
When it happens
Trigger: Calling selectDirectory(dir) where File.getCanonicalPath() fails: unreadable parent directory in the chain, broken symlink, or an OS/filesystem error resolving the absolute path. Existence as a directory is already checked.
Common situations: Restricted directories where the JVM can stat the directory but not traverse a parent for canonicalization; symlink loops; container/namespace filesystem oddities; CI with bind mounts that confuse canonical resolution.
Related errors
- Failed to retrieve canonical path for file
- Could not find any resource(s) with name
- Failed to create a java.net.URI from
- Failed to retrieve canonical path for directory
- Failed to retrieve canonical path for file
AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11).
Data as JSON: /api/errors/ed68793ffd9b7469.
Report an issue: GitHub.
Appendix: source
Thrown at junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java:229
* <p>This method selects the directory in its {@linkplain File#getCanonicalPath()
* canonical} form and throws a {@link PreconditionViolationException} if the
* directory does not exist.
*
* @param directory the directory to select; never {@code null}
* @see DirectorySelector
* @see #selectDirectory(String)
* @see #selectFile(String)
* @see #selectFile(File)
*/
public static DirectorySelector selectDirectory(File directory) {
Preconditions.notNull(directory, "Directory must not be null");
Preconditions.condition(directory.isDirectory(),
() -> "The supplied java.io.File [%s] must represent an existing directory".formatted(directory));
try {
return new DirectorySelector(directory.getCanonicalPath());
}
catch (IOException ex) {
throw new PreconditionViolationException("Failed to retrieve canonical path for directory: " + directory,
ex);
}
}
/**
* Create a list of {@code ClasspathRootSelectors} for the supplied
* <em>classpath roots</em> (directories or JAR files).
*
* <p>Since the supplied paths are converted to {@link URI URIs}, the
* {@link java.nio.file.FileSystem} that created them must be the
* {@linkplain java.nio.file.FileSystems#getDefault() default} or one that
* has been created by an installed
* {@link java.nio.file.spi.FileSystemProvider}.
*
* <p>Since {@linkplain org.junit.platform.engine.TestEngine engines} are not
* expected to modify the classpath, the classpath roots represented by the
* resulting selectors must be on the classpath of the
* {@linkplain Thread#getContextClassLoader() context class loader} of theView on GitHub (pinned to f070c699a0)