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

  1. 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
  2. Sanitize the class path: remove entries with malformed characters or re-encode them (URLEncoder on the path segment)
  3. 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

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


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/c9985c0eec9f31d4. Report an issue: GitHub.