junit-team/junit5 · error · JUnitException
Invalid classpath entry
Error message
Invalid classpath entry: ${path} What it means
ConsoleTestExecutor.toURL() converts a user-supplied --additional-classpath-entry path into a URL for a custom URLClassLoader. If the Path cannot be turned into a URI/URL (typically an IOException or malformed input), a JUnitException wraps the cause. It signals the entry supplied on the command line cannot be used as a classpath root.
Solutions
- Verify the path exists and is on the default/platform FileSystem: Files.exists(path) && path.getFileSystem() == FileSystems.getDefault().
- Convert the entry to a real file on disk (extract or copy) and reference that absolute path.
- If the path is valid but special-character-laden, URL-encode the path or use the file:// URI form directly if supported by the surrounding setup.
- Prefer putting the jar/directory on the real -cp / CLASSPATH instead of --additional-classpath-entry when in doubt.
Example fix
// before java -jar junit-platform-console-standalone.jar execute --additional-classpath-entry /opt/missing/lib.jar // after: ensure the path exists and is a real file ls /opt/missing/lib.jar # fix path java -jar junit-platform-console-standalone.jar execute --additional-classpath-entry /opt/real/lib.jar
Defensive patterns
Strategy: validation
Validate before calling
// Validate the path before passing it as an additional classpath entry.
import java.nio.file.*;
Path p = Paths.get(userEntry);
if (!Files.exists(p)) throw new IllegalArgumentException("classpath entry does not exist: " + userEntry);
if (!Files.isReadable(p)) throw new IllegalArgumentException("classpath entry not readable: " + userEntry);
if (p.getFileSystem() != FileSystems.getDefault())
throw new IllegalArgumentException("classpath entry is not on the default filesystem: " + userEntry);
// If ok, pass --additional-classpath-entry userEntry
Prevention
- Always reference additional classpath entries by absolute paths on local disk.
- Confirm entries exist and are readable before running the launcher.
- Prefer the standard -cp / CLASSPATH over --additional-classpath-entry when possible.
When it happens
Trigger: Passing --additional-classpath-entry with a path that does not exist or whose Path.toUri().toURL() throws — e.g. a path on a non-default FileSystem (a Path inside a zip/jar via a custom provider), a path with characters the URI parser rejects, or a path whose provider does not support URL conversion.
Common situations: Pointing --additional-classpath-entry at a non-existent file, a directory inside a custom FileSystem (e.g. a Path obtained from an opened jar FileSystem), or a path with unencoded special characters. Also seen when the supplied string resolves against an unusual default FileSystem.
Related errors
- Could not open color palette properties file
- Error redirecting stderr to file
- Error redirecting stdout and stderr to file
- Error redirecting stdout to file
- Failed to close custom class loader
AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11).
Data as JSON: /api/errors/f9e1b1321470dca0.
Report an issue: GitHub.
Appendix: source
Thrown at junit-platform-console/src/main/java/org/junit/platform/console/command/ConsoleTestExecutor.java:183
launcher.execute(executionRequest);
}
private @Nullable CustomClassLoader createCustomClassLoader() {
List<Path> additionalClasspathEntries = discoveryOptions.getExistingAdditionalClasspathEntries();
if (!additionalClasspathEntries.isEmpty()) {
URL[] urls = additionalClasspathEntries.stream().map(this::toURL).toArray(URL[]::new);
ClassLoader parentClassLoader = ClassLoaderUtils.getDefaultClassLoader();
return new CustomClassLoader(URLClassLoader.newInstance(urls, parentClassLoader));
}
return null;
}
private URL toURL(Path path) {
try {
return path.toUri().toURL();
}
catch (Exception ex) {
throw new JUnitException("Invalid classpath entry: " + path, ex);
}
}
private SummaryGeneratingListener registerListeners(PrintWriter out, Optional<Path> reportsDir, Launcher launcher,
@Nullable CancellationToken cancellationToken) {
// always register summary generating listener
SummaryGeneratingListener summaryListener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(summaryListener);
// optionally, register test plan execution details printing listener
createDetailsPrintingListener(out).ifPresent(launcher::registerTestExecutionListeners);
// optionally, register XML reports writing listener
createXmlWritingListener(out, reportsDir).ifPresent(launcher::registerTestExecutionListeners);
createFailFastListener(cancellationToken).ifPresent(launcher::registerTestExecutionListeners);
return summaryListener;
}
private Optional<DetailsPrintingListener> createDetailsPrintingListener(PrintWriter out) {View on GitHub (pinned to f070c699a0)