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
- 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).
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
- 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).
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
- Failed to build classpath URLs.
- IO problem while reading files with API signatures.
- Parsing signatures failed: {}
- No signatures were added to task; use properties 'signatures
- Failed to load one of the given class files.
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/cac7936531c49e4d.
Report an issue: GitHub.