{"id":"a47de9a3591af2a8","repo":"junit-team/junit5","slug":"failed-to-retrieve-canonical-path-for-directory-a47de9","errorCode":null,"errorMessage":"Failed to retrieve canonical path for directory: ${directory}","messagePattern":"Failed to retrieve canonical path for directory: (.+?)","errorType":"exception","errorClass":"JUnitException","httpStatus":null,"severity":"error","filePath":"junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DirectorySource.java","lineNumber":55,"sourceCode":"\t/**\n\t * Create a new {@code DirectorySource} using the supplied\n\t * {@linkplain File directory}.\n\t *\n\t * @param directory the source directory; must not be {@code null}\n\t */\n\tpublic static DirectorySource from(File directory) {\n\t\treturn new DirectorySource(directory);\n\t}\n\n\tprivate final File directory;\n\n\tprivate DirectorySource(File directory) {\n\t\tPreconditions.notNull(directory, \"directory must not be null\");\n\t\ttry {\n\t\t\tthis.directory = directory.getCanonicalFile();\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthrow new JUnitException(\"Failed to retrieve canonical path for directory: \" + directory, ex);\n\t\t}\n\t}\n\n\t/**\n\t * Get the {@link URI} for the source {@linkplain #getFile directory}.\n\t *\n\t * @return the source {@code URI}; never {@code null}\n\t */\n\t@Override\n\tpublic URI getUri() {\n\t\treturn getFile().toURI();\n\t}\n\n\t/**\n\t * Get the source {@linkplain File directory}.\n\t *\n\t * @return the source directory; never {@code null}\n\t */","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/junit-team/junit5/blob/956246301e03d757539f7b76dd5a91f298637563/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DirectorySource.java#L37-L73","documentation":"Thrown by the DirectorySource constructor (line 49-57) when directory.getCanonicalFile() raises IOException, wrapped in a JUnitException. DirectorySource.from(File) is used to attach a directory as a TestSource on a TestDescriptor. Unlike the discovery selectors, this path does not pre-check existence.","triggerScenarios":"Calling DirectorySource.from(file) for a directory whose canonical form cannot be resolved (broken symlink chain, removed parent, I/O fault on the filesystem, or an unreachable network mount). Common inside custom engines or extensions that build TestDescriptors for filesystem locations.","commonSituations":"Custom TestEngine/extension creating a TestSource for a directory that later becomes invalid; descriptor created from a stale File reference after the filesystem changed; module-path or container environments with non-standard filesystems.","solutions":["Resolve the canonical File yourself (Path.toRealPath().toFile()) before calling DirectorySource.from(...).","Guard with Files.isDirectory(Path) and Files.isReadable before constructing the source.","Avoid holding long-lived File references to volatile locations; re-resolve at descriptor-creation time.","Surface the caused-by IOException to diagnose the underlying OS/filesystem error."],"exampleFix":"// before\nTestSource source = DirectorySource.from(new File(dirPath)); // throws JUnitException\n\n// after\nFile canonical = Path.of(dirPath).toRealPath().toFile();\nTestSource source = DirectorySource.from(canonical);","handlingStrategy":"validation","validationCode":"File canonical = Path.of(dirPath).toRealPath().toFile(); // clearer error\nTestSource source = DirectorySource.from(canonical);","typeGuard":null,"tryCatchPattern":"try {\n    return DirectorySource.from(dir);\n} catch (JUnitException e) {\n    throw new IllegalStateException(\"cannot build DirectorySource for \" + dir, e.getCause());\n}","preventionTips":["Canonicalize with Path.toRealPath() before constructing DirectorySource.","Guard with Files.isDirectory(Path).","Do not cache File references to volatile paths across descriptor creation."],"tags":["junit-platform","test-source","io","filesystem","directory-source","canonical-path"],"analyzedSha":"956246301e03d757539f7b76dd5a91f298637563","analyzedAt":"2026-08-04T19:25:17.049Z","schemaVersion":2}