{"record":{"id":"473ee720431a87ad","repo":"elastic/elasticsearch","slug":"could-not-load-ssl-private-key-file-473ee7","errorCode":null,"errorMessage":"could not load ssl private key file [{}]","messagePattern":"could not load ssl private key file \\[(.+?)\\]","errorType":"exception","errorClass":"SslConfigException","httpStatus":null,"severity":"error","filePath":"libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java","lineNumber":109,"sourceCode":"     */\n    private static final String DEPRECATED_DES_EDE_ALGORITHM = \"DESede\";\n\n    private PemUtils() {\n        throw new IllegalStateException(\"Utility class should not be instantiated\");\n    }\n\n    /**\n     * Creates a {@link PrivateKey} from the contents of a file and handles any exceptions\n     *\n     * @param path           the path for the key file\n     * @param passwordSupplier A password supplier for the potentially encrypted (password protected) key\n     * @return a private key from the contents of the file\n     */\n    public static PrivateKey readPrivateKey(Path path, Supplier<char[]> passwordSupplier) throws IOException, GeneralSecurityException {\n        try {\n            final PrivateKey privateKey = PemUtils.parsePrivateKey(path, passwordSupplier);\n            if (privateKey == null) {\n                throw new SslConfigException(\"could not load ssl private key file [\" + path + \"]\");\n            }\n            return privateKey;\n        } catch (SecurityException e) {\n            throw SslFileUtil.accessControlFailure(\"PEM private key\", List.of(path), e, null);\n        } catch (IOException e) {\n            throw SslFileUtil.ioException(\"PEM private key\", List.of(path), e);\n        } catch (GeneralSecurityException e) {\n            throw SslFileUtil.securityException(\"PEM private key\", List.of(path), e);\n        }\n    }\n\n    /**\n     * Creates a {@link PrivateKey} from the contents of a file. Supports PKCS#1, PKCS#8\n     * encoded formats of encrypted and plaintext RSA, DSA and EC(secp256r1) keys\n     *\n     * @param keyPath           the path for the key file\n     * @param passwordSupplier A password supplier for the potentially encrypted (password protected) key\n     * @return a private key from the contents of the file","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java#L91-L127","documentation":"Thrown by PemUtils.readPrivateKey() (the public wrapper around parsePrivateKey) when parsePrivateKey returns null. readPrivateKey is the entry point used by other Elastic SSL code that wants SslFileUtil-style error wrapping; the null return means the file was readable but contained no recognised private-key PEM block.","triggerScenarios":"readPrivateKey(path, passwordSupplier) calls parsePrivateKey(path, passwordSupplier); result is null. This is the same condition as error 795 but surfaced through the PemUtils API rather than PemKeyConfig — it indicates the file lacks any of the supported headers (PKCS#1 RSA, PKCS#8, PKCS#8 encrypted, OpenSSL DSA, OpenSSL EC).","commonSituations":"File is empty, contains only a public key, contains an OpenSSH-format key, or is a certificate rather than a private key. Note that parsePrivateKey actually throws SslConfigException for unsupported formats rather than returning null, so a true null is rare and typically comes from a future code path that may return null for an empty/unparseable file.","solutions":["Inspect the first non-blank line of the file — it must start with `-----BEGIN` and match a supported header.","Convert OpenSSH keys to PEM: `ssh-keygen -p -m PEM -f id_rsa`.","Re-export as PKCS#8: `openssl pkcs8 -topk8 -inkey key.pem -out key.pk8.pem -nocrypt`.","Verify the file is a private key (not a cert): `openssl pkey -in key.pem -noout` should succeed."],"exampleFix":"// before: passing a public-key-only file\nPrivateKey pk = PemUtils.readPrivateKey(pubKeyPath, () -> null); // throws\n\n// after: pass the actual private key\nPrivateKey pk = PemUtils.readPrivateKey(privateKeyPath, () -> keyPassword);","handlingStrategy":"validation","validationCode":"public static boolean fileContainsPrivateKey(Path p) throws IOException {\n    try (BufferedReader r = Files.newBufferedReader(p, StandardCharsets.UTF_8)) {\n        String line;\n        while ((line = r.readLine()) != null) {\n            if (line.startsWith(\"-----BEGIN\") && line.contains(\"PRIVATE KEY\")) return true;\n        }\n    }\n    return false;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Confirm the file is a private key (not a certificate or public key).","Convert OpenSSH keys to PKCS#8 PEM.","Use `openssl pkey -in key.pem -noout` to verify before configuring."],"tags":["ssl","pem","private-key","elasticsearch","crypto"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}