{"record":{"id":"c9985c0eec9f31d4","repo":"oracle/graal","slug":"given-uri-s-cannot-be-expressed-as-url","errorCode":null,"errorMessage":"Given URI '%s' cannot be expressed as URL.","messagePattern":"Given URI '(.+?)' cannot be expressed as URL\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccessClassLoader.java","lineNumber":188,"sourceCode":"        remotePackageToLoader = initRemotePackageMap(configuration, List.of(ModuleLayer.boot()));\n\n        /* The only map that gets updated concurrently during the lifetime of this loader. */\n        moduleToReader = new ConcurrentHashMap<>();\n\n        /* Initialize URLClassPath that is used to lookup classes from class-path. */\n        ucp = new URLClassPath(classpath.stream().map(HostVMAccessClassLoader::toURL).toArray(URL[]::new), null);\n\n    }\n\n    private static URL toURL(Path p) {\n        return toURL(p.toUri());\n    }\n\n    private static URL toURL(URI uri) {\n        try {\n            return uri.toURL();\n        } catch (MalformedURLException e) {\n            throw new RuntimeException(\"Given URI '\" + uri + \"' cannot be expressed as URL.\", e);\n        }\n    }\n\n    /**\n     * See {@link jdk.internal.loader.Loader#initRemotePackageMap}.\n     */\n    private Map<String, ClassLoader> initRemotePackageMap(Configuration cf, List<ModuleLayer> parentModuleLayers) {\n        // Checkstyle: stop stable iteration order check\n        Map<String, ClassLoader> remotePackageMap = new HashMap<>();\n        // Checkstyle: resume stable iteration order check\n\n        for (String name : localNameToModule.keySet()) {\n            ResolvedModule resolvedModule = cf.findModule(name).get();\n            assert resolvedModule.configuration() == cf;\n\n            for (ResolvedModule other : resolvedModule.reads()) {\n                String mn = other.name();\n                ClassLoader loader;","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccessClassLoader.java#L170-L206","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nbuilder.classPath(List.of(rawUserPath)); // rawUserPath contains '#'\n\n// after\nURI uri = rawUserPath.toUri();\ntry {\n    uri.toURL(); // pre-validate\n} catch (MalformedURLException e) {\n    throw new IllegalArgumentException(\"Class path entry not URL-convertible: \" + rawUserPath, e);\n}\nbuilder.classPath(List.of(rawUserPath));","handlingStrategy":"validation","validationCode":"for (Path p : classpath) {\n    try {\n        p.toUri().toURL(); // pre-validate URL-convertibility\n    } catch (MalformedURLException e) {\n        throw new IllegalArgumentException(\"Bad class path entry: \" + p, e);\n    }\n}","typeGuard":null,"tryCatchPattern":"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; } }","preventionTips":["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"],"tags":["graalvm","classpath","url","uri","configuration"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}