quarkusio/quarkus · error · IllegalStateException

Invalid key/certificate pair configuration for certificate '

Error message

Invalid key/certificate pair configuration for certificate '${name}'

What it means

Generic failure while turning a configured PEM key/certificate pair into a usable keystore — any non-IO exception from option building or loading is wrapped in this IllegalStateException naming the certificate configuration. It is the catch-all sibling of the more specific 'cannot read the files' error.

Source

Thrown at extensions/tls-registry/runtime/src/main/java/io/quarkus/tls/runtime/keystores/PemKeyStores.java:35

public class PemKeyStores {

    private PemKeyStores() {
        // Avoid direct instantiation
    }

    public static KeyStoreAndKeyCertOptions verifyPEMKeyStore(KeyStoreConfig ksc, Vertx vertx, String name) {
        PemKeyCertConfig config = ksc.pem().orElseThrow();
        if (config.keyCerts().isEmpty()) {
            throw new IllegalStateException("No key/certificate pair configured for certificate '" + name + "'");
        }
        try {
            PemKeyCertOptions options = config.toOptions();
            return new KeyStoreAndKeyCertOptions(options.loadKeyStore(vertx), options);
        } catch (UncheckedIOException e) {
            throw new IllegalStateException("Invalid key/certificate pair configuration for certificate '" + name
                    + "' - cannot read the key/certificate files", e);
        } catch (Exception e) {
            throw new IllegalStateException("Invalid key/certificate pair configuration for certificate '" + name + "'", e);
        }
    }

    public static TrustStoreAndTrustOptions verifyPEMTrustStoreStore(TrustStoreConfig tsc, Vertx vertx, String name) {
        var config = tsc.pem().orElseThrow();
        if (config.hasNoTrustedCertificates()) {
            throw new IllegalStateException("No PEM certificates configured for the trust store of '" + name + "'");
        }
        try {
            var options = config.toOptions();
            KeyStore ks = options.loadKeyStore(vertx);
            if (tsc.certificateExpirationPolicy() == TrustStoreConfig.CertificateExpiryPolicy.IGNORE) {
                return new TrustStoreAndTrustOptions(ks, options);
            } else {
                var wrapped = new ExpiryTrustOptions(options, tsc.certificateExpirationPolicy());
                return new TrustStoreAndTrustOptions(ks, wrapped);
            }
        } catch (UncheckedIOException e) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Confirm the key and cert are a matching pair: compare modulus with openssl x509 -modulus and openssl rsa -modulus
  2. Convert the key to PKCS#8 unencrypted: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key.pk8.pem
  3. Make sure the .key property points to the private key and .cert to the certificate, not swapped
  4. Regenerate the pair if mismatched and reconfigure the paths

Example fix

// before (mismatched pair)
quarkus.tls.my-tls.key-store.pem.0.key=old-key.pem
quarkus.tls.my-tls.key-store.pem.0.cert=new-cert.pem
// after (matching pair)
quarkus.tls.my-tls.key-store.pem.0.key=new-key.pk8.pem
quarkus.tls.my-tls.key-store.pem.0.cert=new-cert.pem
Defensive patterns

Strategy: validation

Validate before calling

// check key/cert pair matches before configuring
PublicKey pub = loadCert(certPath).getPublicKey();
PrivateKey priv = loadKey(keyPath);
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(priv); sig.update("t".getBytes());
sig.initVerify(pub); sig.update("t".getBytes());
if (!sig.verify(sig.sign())) throw new IllegalStateException("key/cert mismatch");

Try / catch

try {
    // use TLS config
} catch (IllegalStateException e) {
    if (e.getMessage().contains("Invalid key/certificate pair configuration")
            && !e.getMessage().contains("cannot read")) {
        log.errorf(e.getCause(), "Key material invalid for %s (mismatch/format?)", certName);
    }
}

Prevention

When it happens

Trigger: verifyPEMKeyStore catches a general Exception from config.toOptions() or options.loadKeyStore(vertx): malformed key material, key/cert mismatch, unsupported key algorithm, or parsing errors that are not UncheckedIOException.

Common situations: Private key and certificate do not form a pair (mismatched files); key is in unsupported format (e.g. 'BEGIN RSA PRIVATE KEY' variants the parser rejects); files swapped (key where cert expected); PKCS#8 vs PKCS#1 key encoding issues.

Understand the failure class

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/53abba2e6bd43f61. Report an issue: GitHub.