elastic/elasticsearch · error · GradleException
Jvm Metadata cannot be resolved for {}
Error message
Jvm Metadata cannot be resolved for {} What it means
Thrown by ErrorTraceMetadataDetector, a decorator around Gradle's JvmMetadataDetector that converts silent failures into hard build errors. When Gradle probes a candidate JAVA_HOME and the probe returns a FailureInstallationMetadata (the JVM could not be inspected), this detector throws a GradleException instead of letting the toolchain fall through to another JVM. It exists so the build fails loudly on an unusable JDK rather than silently picking a wrong one.
Source
Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/GlobalBuildInfoPlugin.java:492
return b.toString();
} catch (IOException e) {
throw new UncheckedIOException("Error trying to read classpath resource: " + resourcePath, e);
}
}
private static class ErrorTraceMetadataDetector implements JvmMetadataDetector {
private final JvmMetadataDetector delegate;
ErrorTraceMetadataDetector(JvmMetadataDetector delegate) {
this.delegate = delegate;
}
@Override
public JvmInstallationMetadata getMetadata(InstallationLocation installationLocation) {
JvmInstallationMetadata metadata = delegate.getMetadata(installationLocation);
if (metadata instanceof JvmInstallationMetadata.FailureInstallationMetadata) {
throw new GradleException("Jvm Metadata cannot be resolved for " + metadata.getJavaHome().toString());
}
return metadata;
}
}
private static class MetadataBasedToolChainMatcher implements Action<JavaToolchainSpec> {
private final JvmVendorSpec expectedVendorSpec;
private final JavaLanguageVersion expectedJavaLanguageVersion;
MetadataBasedToolChainMatcher(JvmInstallationMetadata metadata) {
expectedVendorSpec = JvmVendorSpec.matching(metadata.getVendor().getRawVendor());
expectedJavaLanguageVersion = JavaLanguageVersion.of(metadata.getLanguageVersion().getMajorVersion());
}
@Override
public void execute(JavaToolchainSpec spec) {
spec.getVendor().set(expectedVendorSpec);
spec.getLanguageVersion().set(expectedJavaLanguageVersion);View on GitHub (pinned to db6a809a66)
Solutions
- Verify the JDK is complete: run $JAVA_HOME/bin/java -version and $JAVA_HOME/bin/javac -version; both must succeed.
- Point JAVA_HOME at a fresh full JDK install matching the project's required version (JDK 25 for this repo).
- Run ./gradlew -q javaToolchains to list every detected JVM and confirm the intended one is recognised with valid metadata.
- If using Gradle auto-provisioning, clear the toolchain cache (~/.gradle/jdks) and let it re-download.
- Loosen or correct the toolchain vendor/version spec in build-conventions if it excludes the only available JDK.
Example fix
// before: JAVA_HOME=/opt/jre-21 (JRE only, no javac) // after: export JAVA_HOME=/opt/jdk-25; java -version && javac -version
Defensive patterns
Strategy: validation
Validate before calling
// Validate the candidate JAVA_HOME before letting the build resolve the toolchain
File javaHome = new File(System.getenv("JAVA_HOME"));
File javaBin = new File(javaHome, "bin/java" + (System.getProperty("os.name").startsWith("Windows") ? ".exe" : ""));
File javacBin = new File(javaHome, "bin/javac" + (System.getProperty("os.name").startsWith("Windows") ? ".exe" : ""));
if (!javaBin.isFile() || !javacBin.isFile()) {
throw new IllegalStateException("JAVA_HOME does not point to a complete JDK: " + javaHome);
}
File release = new File(javaHome, "release");
if (!release.isFile()) {
throw new IllegalStateException("Not a JDK home (no 'release' file): " + javaHome);
} Try / catch
// Global build-init guard
try {
project.getExtensions().getByType(JavaPluginExtension.class).getToolchain();
} catch (GradleException e) {
if (e.getMessage().contains("Jvm Metadata cannot be resolved")) {
throw new GradleException("Toolchain JDK unusable. Run `./gradlew -q javaToolchains` and fix JAVA_HOME.", e);
}
throw e;
} Prevention
- Pin JAVA_HOME to a full JDK (not a JRE) matching the project's required version.
- Document the required JDK version in BUILDING.md and CI setup scripts.
- In CI, install JDKs via a toolchain manager (sdkman/asdf) that guarantees a complete install.
- Run `./gradlew -q javaToolchains` in onboarding to confirm detection.
When it happens
Trigger: Triggered when the Java toolchain resolution calls getMetadata on an InstallationLocation whose delegate returns FailureInstallationMetadata — i.e., the pointed-to javaHome exists but is not a valid/complete JDK (missing release file, broken java executable, wrong arch, or a JRE rather than a JDK).
Common situations: JAVA_HOME pointing at a stripped/partial JDK install; a JDK auto-provisioned by Gradle that got corrupted mid-download; switching JDK distribution with a stale JAVA_HOME; a CI image shipping only a JRE; a macOS .jdk bundle whose Contents/Home was altered; toolchain.vendor/version constraints that no installed JVM satisfies.
Related errors
- Operating system {}
- Architecture {}
- ExtractForeignApiTask worker must run on JDK 21 (found JDK $
- Configuring a snapshot bwc distribution ('${distribution.get
- unknown vendor [${vendor}] for jdk [${name}], must be one of
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/feace50d96793606.
Report an issue: GitHub.