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

  1. Verify the JDK is complete: run $JAVA_HOME/bin/java -version and $JAVA_HOME/bin/javac -version; both must succeed.
  2. Point JAVA_HOME at a fresh full JDK install matching the project's required version (JDK 25 for this repo).
  3. Run ./gradlew -q javaToolchains to list every detected JVM and confirm the intended one is recognised with valid metadata.
  4. If using Gradle auto-provisioning, clear the toolchain cache (~/.gradle/jdks) and let it re-download.
  5. 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

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


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