{"record":{"id":"44adbfab6475a16b","repo":"elastic/elasticsearch","slug":"error-trying-to-read-classpath-resource","errorCode":null,"errorMessage":"Error trying to read classpath resource: {}","messagePattern":"Error trying to read classpath resource: (.+?)","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/GlobalBuildInfoPlugin.java","lineNumber":477,"sourceCode":"        return toolChainService.launcherFor(javaToolchainSpec -> javaToolchainSpec.getLanguageVersion().value(value))\n            .map(launcher -> launcher.getMetadata().getInstallationPath().getAsFile());\n    }\n\n    public static String getResourceContents(String resourcePath) {\n        try (\n            BufferedReader reader = new BufferedReader(new InputStreamReader(GlobalBuildInfoPlugin.class.getResourceAsStream(resourcePath)))\n        ) {\n            StringBuilder b = new StringBuilder();\n            for (String line = reader.readLine(); line != null; line = reader.readLine()) {\n                if (b.length() != 0) {\n                    b.append('\\n');\n                }\n                b.append(line);\n            }\n\n            return b.toString();\n        } catch (IOException e) {\n            throw new UncheckedIOException(\"Error trying to read classpath resource: \" + resourcePath, e);\n        }\n    }\n\n    private static class ErrorTraceMetadataDetector implements JvmMetadataDetector {\n        private final JvmMetadataDetector delegate;\n\n        ErrorTraceMetadataDetector(JvmMetadataDetector delegate) {\n            this.delegate = delegate;\n        }\n\n        @Override\n        public JvmInstallationMetadata getMetadata(InstallationLocation installationLocation) {\n            JvmInstallationMetadata metadata = delegate.getMetadata(installationLocation);\n            if (metadata instanceof JvmInstallationMetadata.FailureInstallationMetadata) {\n                throw new GradleException(\"Jvm Metadata cannot be resolved for \" + metadata.getJavaHome().toString());\n            }\n            return metadata;\n        }","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/GlobalBuildInfoPlugin.java#L459-L495","documentation":"Thrown by GlobalBuildInfoPlugin.getResourceContents(String) when reading a classpath resource via GlobalBuildInfoPlugin.class.getResourceAsStream(resourcePath) fails with IOException. This method reads small text resources bundled in the build-tools-internal JAR, such as '/minimumGradleVersion' and '/minimumRuntimeVersion'. The IOException is wrapped in UncheckedIOException.","triggerScenarios":"getResourceAsStream returns a non-null stream (resource exists), but reading from it throws IOException. This is extremely rare in practice since classpath resources are typically packaged correctly. More commonly, if the resource is missing, getResourceAsStream returns null and the BufferedReader/InputStreamReader throws NullPointerException before IOException — which would not be caught by this handler.","commonSituations":"The build-tools-internal JAR is corrupted or incompletely built (resource is present in the manifest but truncated in the archive). A custom classloader interferes with resource loading. The resource is present but on a classpath source that becomes unavailable mid-read (e.g., a JAR on a network mount that disconnects).","solutions":["Rebuild the build-tools-internal project: ./gradlew :build-tools-internal:build.","Run a clean build to regenerate all JARs: ./gradlew clean build.","Verify the resource exists in the JAR: jar tf build-tools-internal/build/libs/*.jar | grep minimumGradleVersion.","If using a composite build, ensure the build-tools-internal project is properly included and its resources are generated."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate resource exists before reading\ntry (var is = GlobalBuildInfoPlugin.class.getResourceAsStream(resourcePath)) {\n    if (is == null) {\n        throw new FileNotFoundException(\"Classpath resource not found: \" + resourcePath);\n    }\n    // safe to read\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run ./gradlew clean build to regenerate all JARs and resources.","Verify resources are included in the JAR: jar tf <jar> | grep <resource>.","Avoid modifying generated/bundled resources directly; edit their source and rebuild."],"tags":["classpath","resources","build-infrastructure","io"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}