{"record":{"id":"cac7936531c49e4d","repo":"elastic/elasticsearch","slug":"failed-to-build-foreign-api-jar-url","errorCode":null,"errorMessage":"Failed to build foreign API JAR URL.","messagePattern":"Failed to build foreign API JAR URL\\.","errorType":"validation","errorClass":"InvalidUserDataException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckForbiddenApisTask.java","lineNumber":584,"sourceCode":"            final URL[] urls = new URL[cpElements.size()];\n            try {\n                int i = 0;\n                for (final File cpElement : cpElements) {\n                    urls[i++] = cpElement.toURI().toURL();\n                }\n                assert i == urls.length;\n            } catch (MalformedURLException mfue) {\n                throw new InvalidUserDataException(\"Failed to build classpath URLs.\", mfue);\n            }\n\n            RegularFileProperty foreignApiJarProp = getParameters().getForeignApiJar();\n            if (foreignApiJarProp.isPresent()) {\n                try {\n                    File jarFile = foreignApiJarProp.getAsFile().get();\n                    URL foreignJarUrl = jarFile.toURI().toURL();\n                    return new ForeignFirstClassLoader(foreignJarUrl, urls, ClassLoader.getSystemClassLoader());\n                } catch (MalformedURLException mfue) {\n                    throw new InvalidUserDataException(\"Failed to build foreign API JAR URL.\", mfue);\n                }\n            }\n            return URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());\n        }\n\n        /**\n         * A classloader that checks its own URLs before delegating to the parent for\n         * classes and resources under {@code java/lang/foreign/}. This allows a\n         * de-previewed stub JAR to shadow the runtime JDK's preview API classes, so\n         * that forbidden-apis can resolve method signatures for JDK 21 preview APIs\n         * that were renamed in JDK 22.\n         *\n         * For all other classes, standard parent-first delegation applies.\n         */\n        private static class ForeignFirstClassLoader extends URLClassLoader {\n            private static final String FOREIGN_RESOURCE_PREFIX = \"java/lang/foreign/\";\n\n            ForeignFirstClassLoader(URL foreignJarUrl, URL[] classpathUrls, ClassLoader parent) {","sourceCodeStart":566,"sourceCodeEnd":602,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckForbiddenApisTask.java#L566-L602","documentation":"Thrown when the foreign API jar (used to de-preview JDK 21 foreign-memory signatures so forbidden-apis can resolve them on JDK 22+) cannot be converted to a URL. This path is only taken when foreignApiJar.isPresent(); a MalformedURLException occurred on jarFile.toURI().toURL().","triggerScenarios":"A foreignApiJar RegularFile whose path fails toURI().toURL(), or whose underlying file is missing/invalid when the URL is built.","commonSituations":"The foreign-api stub jar was deleted or its path changed; the property is wired to a generated artifact that was not produced; unusual characters in the jar path.","solutions":["Check the foreignApiJar property wiring — confirm the jar exists at execution time.","If the stub jar is generated by another task, ensure it is declared as a dependency of this task so it is built first.","Inspect the wrapped MalformedURLException for the failing path; normalise the path if needed.","If foreign API checking is not needed for this task, leave foreignApiJar unset (the code falls back to a plain URLClassLoader)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Only set foreignApiJar when the file genuinely exists, otherwise leave it absent\nRegularFileProperty p = getParameters().getForeignApiJar();\nif (p.isPresent()) {\n    File jar = p.getAsFile().get();\n    if (!jar.isFile()) throw new InvalidUserDataException(\"foreignApiJar missing on disk: \" + jar);\n}","typeGuard":null,"tryCatchPattern":"try {\n    URL foreignJarUrl = jarFile.toURI().toURL();\n} catch (MalformedURLException e) {\n    // re-point foreignApiJar at a valid jar, or unset it if foreign checking is not needed\n    throw e;\n}","preventionTips":["Wire foreignApiJar only to a jar produced by a task this task depends on.","Leave foreignApiJar unset for tasks that do not need JDK foreign-API resolution.","Run the generating task before this one (declare task dependency)."],"tags":["gradle","forbidden-apis","precommit","foreign-api","url"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}