{"record":{"id":"d9915edf7d8a8fdd","repo":"elastic/elasticsearch","slug":"74-d9915e","errorCode":"74","errorMessage":"Plugin checksum missing: {}","messagePattern":"Plugin checksum missing: (.+?)","errorType":"exception","errorClass":"UserException","httpStatus":null,"severity":"error","filePath":"distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/InstallPluginAction.java","lineNumber":582,"sourceCode":"    private Path downloadAndValidate(final String urlString, final Path tmpDir, final boolean officialPlugin) throws IOException,\n        UserException, URISyntaxException {\n        Path zip = downloadZip(urlString, tmpDir);\n        pathsToDeleteOnShutdown.add(zip);\n        String checksumUrlString = urlString + \".sha512\";\n        URL checksumUrl = openUrl(checksumUrlString);\n        String digestAlgo = \"SHA-512\";\n        if (checksumUrl == null && officialPlugin == false) {\n            // fallback to sha1, until 7.0, but with warning\n            terminal.println(\n                \"Warning: sha512 not found, falling back to sha1. This behavior is deprecated and will be removed in a \"\n                    + \"future release. Please update the plugin to use a sha512 checksum.\"\n            );\n            checksumUrlString = urlString + \".sha1\";\n            checksumUrl = openUrl(checksumUrlString);\n            digestAlgo = \"SHA-1\";\n        }\n        if (checksumUrl == null) {\n            throw new UserException(ExitCodes.IO_ERROR, \"Plugin checksum missing: \" + checksumUrlString);\n        }\n        final String expectedChecksum;\n        try (InputStream in = urlOpenStream(checksumUrl)) {\n            /*\n             * The supported format of the SHA-1 files is a single-line file containing the SHA-1. The supported format of the SHA-512 files\n             * is a single-line file containing the SHA-512 and the filename, separated by two spaces. For SHA-1, we verify that the hash\n             * matches, and that the file contains a single line. For SHA-512, we verify that the hash and the filename match, and that the\n             * file contains a single line.\n             */\n            final BufferedReader checksumReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));\n            if (digestAlgo.equals(\"SHA-1\")) {\n                expectedChecksum = checksumReader.readLine();\n            } else {\n                final String checksumLine = checksumReader.readLine();\n                final String[] fields = checksumLine.split(\" {2}\");\n                if (officialPlugin && fields.length != 2 || officialPlugin == false && fields.length > 2) {\n                    throw new UserException(ExitCodes.IO_ERROR, \"Invalid checksum file at \" + checksumUrl);\n                }","sourceCodeStart":564,"sourceCodeEnd":600,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/InstallPluginAction.java#L564-L600","documentation":"Thrown after checksum resolution: the code first tries <url>.sha512, and for non-official plugins falls back to <url>.sha1 with a deprecation warning. If both are missing (checksumUrl still null), a UserException with IO_ERROR (74) is raised naming the last attempted checksum URL string.","triggerScenarios":"Hosting a custom plugin zip without publishing a matching .sha512 (or .sha1) checksum file alongside it; the checksum host returns 404; proxy/network blocks the checksum request but not the zip request.","commonSituations":"Self-hosted/internal plugin repositories that omit checksum files; misconfigured reverse proxies stripping checksum requests.","solutions":["Publish a SHA-512 checksum file at <plugin-url>.sha512 containing `<hash>  <filename>`.","For custom non-official plugins, a `.sha1` fallback is supported (deprecated) — generate it alongside the zip.","Ensure the host serving the zip also serves the checksum with the same path suffix and correct permissions."],"exampleFix":"# before\n# server hosts myplugin.zip only\n# after\nsha512sum myplugin.zip > myplugin.zip.sha512\n# serve both myplugin.zip and myplugin.zip.sha512","handlingStrategy":"validation","validationCode":"String zipUrl = \"https://host/myplugin.zip\";\nfor (String suffix : new String[]{\".sha512\", \".sha1\"}) {\n    if (!canHead(zipUrl + suffix)) {\n        throw new IllegalStateException(\"Missing checksum file at \" + zipUrl + suffix);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always publish a `.sha512` alongside every custom plugin zip.","Run a pre-flight HEAD request for the checksum URL in CI before invoking the installer."],"tags":["plugin-install","checksum","io-error","elasticsearch"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}