junit-team/junit5 · error · PreconditionViolationException

Failed to retrieve canonical path for file: ${file}

Error message

Failed to retrieve canonical path for file: ${file}

What it means

Thrown by DiscoverySelectors.selectFile(File, FilePosition) at line 183-188 when file.getCanonicalPath() raises IOException. selectFile(File) requires the path to be an existing regular file (Preconditions.condition at line 181) before this point, so the canonical resolution fails on a file that does exist but whose canonical form cannot be computed.

Source

Thrown at junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java:187

	 *
	 * @param file the file to select; never {@code null}
	 * @param position the position inside the file; may be {@code null}
	 * @see FileSelector
	 * @see #selectFile(File)
	 * @see #selectFile(String)
	 * @see #selectFile(String, FilePosition)
	 * @see #selectDirectory(String)
	 * @see #selectDirectory(File)
	 */
	public static FileSelector selectFile(File file, @Nullable FilePosition position) {
		Preconditions.notNull(file, "File must not be null");
		Preconditions.condition(file.isFile(),
			() -> "The supplied java.io.File [%s] must represent an existing file".formatted(file));
		try {
			return new FileSelector(file.getCanonicalPath(), position);
		}
		catch (IOException ex) {
			throw new PreconditionViolationException("Failed to retrieve canonical path for file: " + file, ex);
		}
	}

	/**
	 * Create a {@code DirectorySelector} for the supplied directory path.
	 *
	 * <p>This method selects the directory using the supplied path <em>as is</em>,
	 * without verifying if the directory exists.
	 *
	 * @param path the path to the directory to select; never {@code null} or blank
	 * @see DirectorySelector
	 * @see #selectDirectory(File)
	 * @see #selectFile(String)
	 * @see #selectFile(File)
	 */
	public static DirectorySelector selectDirectory(String path) {
		Preconditions.notBlank(path, "Directory path must not be null or blank");
		return new DirectorySelector(path);

View on GitHub (pinned to 956246301e)

Solutions

  1. Check file.getCanonicalFile() yourself first and handle IOException before building the selector.
  2. Resolve the canonical path via java.nio.file.Path.toRealPath() which gives clearer errors, then build the File from it.
  3. Avoid selecting through symlinks; canonicalize the target path once and store the resolved form.
  4. Ensure the underlying filesystem/mount is healthy and accessible at selection time.

Example fix

// before
var selector = DiscoverySelectors.selectFile(new File(path)); // throws on broken symlink

// after
File canonical = Path.of(path).toRealPath().toFile();
var selector = DiscoverySelectors.selectFile(canonical.getCanonicalPath()); // String overload, no re-resolution
Defensive patterns

Strategy: validation

Validate before calling

File f = new File(path);
if (!f.isFile()) throw new IllegalArgumentException("not a file: " + f);
File canonical = Path.of(path).toRealPath().toFile(); // throws a clearer exception on failure
var selector = DiscoverySelectors.selectFile(canonical.getCanonicalPath()); // String overload

Try / catch

try {
    return DiscoverySelectors.selectFile(file);
} catch (PreconditionViolationException e) {
    throw new IllegalStateException("cannot canonicalize file: " + file, e.getCause());
}

Prevention

When it happens

Trigger: Calling selectFile(file) where 'file' passes isFile() but the filesystem cannot resolve its canonical path (broken symlinks in a loop, removed parent directory, I/O error reading the filesystem metadata, or a path on a failing/unmounted network filesystem).

Common situations: Symlink chains that became invalid between isFile() and getCanonicalPath(); files on NFS/SMB shares that dropped; containers where the underlying mount was removed; very deep paths hitting OS limits; security managers denying canonical-path resolution.

Related errors


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