oracle/graal · error · RuntimeException
Given URI '%s' cannot be expressed as URL.
Error message
Given URI '%s' cannot be expressed as URL.
What it means
HostVMAccessClassLoader converts each class-path entry Path to a URL (URLClassPath only accepts URLs). If Path.toUri().toURL() throws MalformedURLException — the URI's scheme is not URL-representable — this RuntimeException wraps it. Typical non-convertible inputs are files with characters the URL parser rejects, or URIs with opaque/exotic schemes.
Source
Thrown at compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccessClassLoader.java:188
remotePackageToLoader = initRemotePackageMap(configuration, List.of(ModuleLayer.boot()));
/* The only map that gets updated concurrently during the lifetime of this loader. */
moduleToReader = new ConcurrentHashMap<>();
/* Initialize URLClassPath that is used to lookup classes from class-path. */
ucp = new URLClassPath(classpath.stream().map(HostVMAccessClassLoader::toURL).toArray(URL[]::new), null);
}
private static URL toURL(Path p) {
return toURL(p.toUri());
}
private static URL toURL(URI uri) {
try {
return uri.toURL();
} catch (MalformedURLException e) {
throw new RuntimeException("Given URI '" + uri + "' cannot be expressed as URL.", e);
}
}
/**
* See {@link jdk.internal.loader.Loader#initRemotePackageMap}.
*/
private Map<String, ClassLoader> initRemotePackageMap(Configuration cf, List<ModuleLayer> parentModuleLayers) {
// Checkstyle: stop stable iteration order check
Map<String, ClassLoader> remotePackageMap = new HashMap<>();
// Checkstyle: resume stable iteration order check
for (String name : localNameToModule.keySet()) {
ResolvedModule resolvedModule = cf.findModule(name).get();
assert resolvedModule.configuration() == cf;
for (ResolvedModule other : resolvedModule.reads()) {
String mn = other.name();
ClassLoader loader;View on GitHub (pinned to a66e9ccd1d)
Solutions
- Normalize/encode the path before passing it: build the URL from the Path and pass only convertible entries — e.g. pre-check path.toUri().toURL() and fail with a clear message naming the entry
- Sanitize the class path: remove entries with malformed characters or re-encode them (URLEncoder on the path segment)
- Avoid URI-producing indirection: pass simple absolute file paths that Path.toUri() turns into well-formed file: URIs
Example fix
// before
builder.classPath(List.of(rawUserPath)); // rawUserPath contains '#'
// after
URI uri = rawUserPath.toUri();
try {
uri.toURL(); // pre-validate
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Class path entry not URL-convertible: " + rawUserPath, e);
}
builder.classPath(List.of(rawUserPath)); Defensive patterns
Strategy: validation
Validate before calling
for (Path p : classpath) {
try {
p.toUri().toURL(); // pre-validate URL-convertibility
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Bad class path entry: " + p, e);
}
} Try / catch
catch (RuntimeException e) { if (e.getMessage().contains("cannot be expressed as URL")) { identify the offending entry from the URI in the message and fix/encode it; } } Prevention
- Pre-validate every class path entry with toUri().toURL() before building VMAccess
- Prefer plain absolute file paths; avoid hand-built URIs in config files
- Quote/escape paths with spaces, # and % in build scripts
When it happens
Trigger: VMAccess.Builder.classPath containing a Path whose toUri() yields a URI that toURL() cannot express — e.g. paths with unencoded characters on some platforms, or unusual scheme/authority combinations. The exception aborts loader construction.
Common situations: Class paths built from user input or config files with special characters (#, %, spaces handled inconsistently); paths coming from other JVMs/containers with opaque URI forms; Windows UNC or drive paths in edge encodings.
Related errors
- LogFile substitution %s cannot be combined with any other ch
- Profile file for path %s exists already
- too many counters, reduce number of counters or increase -XX
- invalid arguments to BenchmarkDynamicCounters: (err|out),sta
- invalid arguments to BenchmarkDynamicCounters: err|out
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/c9985c0eec9f31d4.
Report an issue: GitHub.