elastic/elasticsearch · error · InvalidUserDataException

Failed to build foreign API JAR URL.

Error message

Failed to build foreign API JAR URL.

What it means

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().

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckForbiddenApisTask.java:584

            final URL[] urls = new URL[cpElements.size()];
            try {
                int i = 0;
                for (final File cpElement : cpElements) {
                    urls[i++] = cpElement.toURI().toURL();
                }
                assert i == urls.length;
            } catch (MalformedURLException mfue) {
                throw new InvalidUserDataException("Failed to build classpath URLs.", mfue);
            }

            RegularFileProperty foreignApiJarProp = getParameters().getForeignApiJar();
            if (foreignApiJarProp.isPresent()) {
                try {
                    File jarFile = foreignApiJarProp.getAsFile().get();
                    URL foreignJarUrl = jarFile.toURI().toURL();
                    return new ForeignFirstClassLoader(foreignJarUrl, urls, ClassLoader.getSystemClassLoader());
                } catch (MalformedURLException mfue) {
                    throw new InvalidUserDataException("Failed to build foreign API JAR URL.", mfue);
                }
            }
            return URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());
        }

        /**
         * A classloader that checks its own URLs before delegating to the parent for
         * classes and resources under {@code java/lang/foreign/}. This allows a
         * de-previewed stub JAR to shadow the runtime JDK's preview API classes, so
         * that forbidden-apis can resolve method signatures for JDK 21 preview APIs
         * that were renamed in JDK 22.
         *
         * For all other classes, standard parent-first delegation applies.
         */
        private static class ForeignFirstClassLoader extends URLClassLoader {
            private static final String FOREIGN_RESOURCE_PREFIX = "java/lang/foreign/";

            ForeignFirstClassLoader(URL foreignJarUrl, URL[] classpathUrls, ClassLoader parent) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Check the foreignApiJar property wiring — confirm the jar exists at execution time.
  2. If the stub jar is generated by another task, ensure it is declared as a dependency of this task so it is built first.
  3. Inspect the wrapped MalformedURLException for the failing path; normalise the path if needed.
  4. If foreign API checking is not needed for this task, leave foreignApiJar unset (the code falls back to a plain URLClassLoader).
Defensive patterns

Strategy: validation

Validate before calling

// Only set foreignApiJar when the file genuinely exists, otherwise leave it absent
RegularFileProperty p = getParameters().getForeignApiJar();
if (p.isPresent()) {
    File jar = p.getAsFile().get();
    if (!jar.isFile()) throw new InvalidUserDataException("foreignApiJar missing on disk: " + jar);
}

Try / catch

try {
    URL foreignJarUrl = jarFile.toURI().toURL();
} catch (MalformedURLException e) {
    // re-point foreignApiJar at a valid jar, or unset it if foreign checking is not needed
    throw e;
}

Prevention

When it happens

Trigger: A foreignApiJar RegularFile whose path fails toURI().toURL(), or whose underlying file is missing/invalid when the URL is built.

Common situations: 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.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/cac7936531c49e4d. Report an issue: GitHub.