{"record":{"id":"381f7c3b0192072b","repo":"quarkusio/quarkus","slug":"failed-to-create-a-url-for-file","errorCode":null,"errorMessage":"Failed to create a URL for '<file>'","messagePattern":"Failed to create a URL for '<file>'","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoaders.java","lineNumber":60,"sourceCode":"        if (f.isDirectory()) {\n            return new DirectoryResourceLoader(f.toPath());\n        }\n        if (f.isFile() && FilenameUtils.isExtension(f.getName(), \"jar\", \"zip\")) {\n            return new ZipResourceLoader(f.toPath());\n        }\n        throw new IllegalStateException(\"No compatible ResourceLoader have been found for file type: \" + f.getName());\n    }\n\n    // This method is copied from io.quarkus.runtime.util.ClassPathUtils\n    public static <R> R processAsPath(URL url, Function<Path, R> function) {\n        if (JAR.equals(url.getProtocol())) {\n            final String file = url.getFile();\n            final int exclam = file.lastIndexOf('!');\n            final Path jar;\n            try {\n                jar = toLocalPath(exclam >= 0 ? new URL(file.substring(0, exclam)) : url);\n            } catch (MalformedURLException e) {\n                throw new RuntimeException(\"Failed to create a URL for '\" + file.substring(0, exclam) + \"'\", e);\n            }\n            try (FileSystem jarFs = ZipUtils.newFileSystem(jar)) {\n                Path localPath = jarFs.getPath(\"/\");\n                if (exclam >= 0) {\n                    localPath = localPath.resolve(file.substring(exclam + 1));\n                }\n                return function.apply(localPath);\n            } catch (IOException e) {\n                throw new UncheckedIOException(\"Failed to read \" + jar, e);\n            }\n        }\n\n        if (FILE.equals(url.getProtocol())) {\n            return function.apply(toLocalPath(url));\n        }\n\n        throw new IllegalArgumentException(\"Unexpected protocol \" + url.getProtocol() + \" for URL \" + url);\n    }","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/tools/devtools-common/src/main/java/io/quarkus/platform/descriptor/loader/json/ResourceLoaders.java#L42-L78","documentation":"ResourceLoaders.processAsPath resolves a resource URL into a filesystem Path so a consumer function can read it. When the URL points inside a nested JAR, it strips the '!...' suffix and converts the JAR URL to a local Path; if that sub-URL is malformed (cannot be parsed as a URL), a RuntimeException wrapping MalformedURLException is thrown with this message.","triggerScenarios":"Calling loadResourceAsPath/processAsPath with a URL whose file portion contains a '!' but whose part before the last '!' is not a valid URL (e.g. a plain path 'file1.jar' with no scheme, or an improperly encoded URL string).","commonSituations":"Spring Boot-style fat/nested JARs (jar:file:...!/...!/...) where the nested entry is extracted incorrectly; custom classloaders constructing non-standard 'jar:' URLs; corrupted MANIFEST classpath entries with malformed jar paths.","solutions":["Print the offending URL and check the text before the last '!' is a fully-formed URL with scheme (e.g. file:/path/to.jar)","Fix the code that constructed the URL so the JAR part includes its scheme (prepend 'file:' if it came from a raw path)","If the resource is on the local filesystem, ensure it is passed as a 'file:' URL so the FILE protocol branch is used instead of the nested-JAR branch"],"exampleFix":"// before\nURL url = new URL(\"/opt/app/lib/quarkus.jar!/quarkus-extension.yaml\"); // MalformedURLException downstream\n// after\nURL url = new URL(\"file:/opt/app/lib/quarkus.jar!/quarkus-extension.yaml\");","handlingStrategy":"validation","validationCode":"static boolean safeNestedJarUrl(URL url) {\n    String f = url.getFile();\n    int exclam = f.lastIndexOf('!');\n    if (exclam < 0) return true;\n    try { new URL(f.substring(0, exclam)); return true; }\n    catch (MalformedURLException e) { return false; }\n}","typeGuard":"static boolean hasJarScheme(URL url) {\n    String f = url.getFile();\n    int i = f.lastIndexOf('!');\n    return i < 0 || f.startsWith(\"file:\", 0) && i > \"file:\".length();\n}","tryCatchPattern":"try {\n    ResourceLoaders.processAsPath(url, fn);\n} catch (RuntimeException e) {\n    if (e.getCause() instanceof MalformedURLException) {\n        throw new IllegalStateException(\"Malformed nested-jar URL: \" + url, e);\n    }\n    throw e;\n}","preventionTips":["Build URLs with File.toURI().toURL() or Path.toUri().toURL(), never string concatenation","Only pass jar-style URLs produced by standard classloaders into ResourceLoaders","Log the full URL before processing so malformed pieces are visible in failures"],"tags":["url","classpath","jar","malformed-url"],"backgroundTag":"malformed-jar-url","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}