elastic/elasticsearch · error · SslConfigException

failed to parse any certificates from [{}]

Error message

failed to parse any certificates from [{}]

What it means

Thrown by readCertificates when CertificateFactory.generateCertificates returns an empty collection for a given path. This is an SslConfigException (not a CertificateException) indicating the file exists and is readable but contains no parseable X.509 certificates — the file is empty, contains only a private key, holds non-PEM/non-DER content, or the cert body is corrupted.

Source

Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java:692

        String oidString = parser.readAsn1Object().getOid();
        return switch (oidString) {
            case "1.2.840.10040.4.1" -> "DSA";
            case "1.2.840.113549.1.1.1" -> "RSA";
            case "1.2.840.10045.2.1" -> "EC";
            default -> throw new GeneralSecurityException(
                "Error parsing key algorithm identifier. Algorithm with OID [" + oidString + "] is not supported"
            );
        };
    }

    public static List<Certificate> readCertificates(Collection<Path> certPaths) throws CertificateException, IOException {
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        List<Certificate> certificates = new ArrayList<>(certPaths.size());
        for (Path path : certPaths) {
            try (InputStream input = Files.newInputStream(path)) {
                final Collection<? extends Certificate> parsed = certFactory.generateCertificates(input);
                if (parsed.isEmpty()) {
                    throw new SslConfigException("failed to parse any certificates from [" + path.toAbsolutePath() + "]");
                }
                certificates.addAll(parsed);
            }
        }
        return certificates;
    }

    private static String getAlgorithmNameFromOid(String oidString) throws GeneralSecurityException {
        return switch (oidString) {
            case "1.2.840.10040.4.1" -> "DSA";
            case "1.2.840.113549.1.1.1" -> "RSA";
            case "1.2.840.10045.2.1" -> "EC";
            case "1.3.14.3.2.7" -> "DES-CBC";
            case "2.16.840.1.101.3.4.1.1" -> "AES-128_ECB";
            case "2.16.840.1.101.3.4.1.2" -> "AES-128_CBC";
            case "2.16.840.1.101.3.4.1.3" -> "AES-128_OFB";
            case "2.16.840.1.101.3.4.1.4" -> "AES-128_CFB";
            case "2.16.840.1.101.3.4.1.6" -> "AES-128_GCM";

View on GitHub (pinned to db6a809a66)

Solutions

  1. Verify the file contains one or more '-----BEGIN CERTIFICATE-----' ... '-----END CERTIFICATE-----' blocks (or is a valid DER-encoded certificate).
  2. Regenerate or re-export the certificate: 'openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes'.
  3. Confirm the config points at the certificate file, not the key: e.g. xpack.security.transport.ssl.certificate.
  4. Check the file is non-empty: 'ls -l <file>' and 'head -1 <file>'.

Example fix

// before: certificate setting points at the private key
xpack.security.transport.ssl.certificate: /etc/elasticsearch/certs/node.key
// after: certificate setting points at the certificate PEM
xpack.security.transport.ssl.certificate: /etc/elasticsearch/certs/node.crt.pem
Defensive patterns

Strategy: validation

Validate before calling

// Before calling readCertificates, confirm the file is non-empty and contains at least one CERTIFICATE block
static boolean hasCertificate(Path p) throws IOException {
    try (BufferedReader r = Files.newBufferedReader(p, StandardCharsets.UTF_8)) {
        String line; boolean sawCert = false;
        while ((line = r.readLine()) != null) {
            if (line.trim().equals("-----BEGIN CERTIFICATE-----")) sawCert = true;
            if (line.trim().equals("-----END CERTIFICATE-----") && sawCert) return true;
        }
    }
    return false;
}
// Also: if (Files.size(p) == 0) throw new IllegalArgumentException("certificate file is empty");

Try / catch

try { List<Certificate> certs = PemUtils.readCertificates(List.of(path)); }
catch (SslConfigException e) { if (e.getMessage().contains("failed to parse any certificates")) { /* point at the cert file */ } else throw e; }

Prevention

When it happens

Trigger: Pointing a certificate configuration at a file that contains no certificates (e.g. only a private key, a CSR, a CRL, plain text, or an empty file); a certificate file whose BEGIN/END CERTIFICATE markers were stripped; a DER file that is actually something else.

Common situations: Swapping the certificate and key arguments in xpack.ssl settings; pointing at an empty placeholder file; a templating system that stripped the PEM markers; a file that was truncated to zero bytes by a failed deployment; using a PEM that contains only the chain intermediates with the wrong filename.

Understand the failure class

Related errors


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