quarkusio/quarkus · error · IllegalStateException

Invalid key/certificate pair configuration for certificate

Error message

Invalid key/certificate pair configuration for certificate '${name}' - cannot read the key/certificate files

What it means

Thrown when the PEM key/certificate files configured for a named TLS certificate configuration cannot be read from disk — the load raised UncheckedIOException. The configuration is structurally valid, but the files themselves are inaccessible or unreadable.

Solutions

  1. Verify both key and cert files exist and are readable at the configured paths (ls -l / cat test)
  2. Use absolute paths in quarkus.tls.<name>.key-store.pem.<n>.key/.cert so runtime cwd does not matter
  3. Check the PEM content is valid unencrypted PEM (-----BEGIN PRIVATE KEY----- / CERTIFICATE----- headers)
  4. Include the files in the container/deployment artifact if running in a container

Example fix

// before
quarkus.tls.my-tls.key-store.pem.0.key=./server-key.pem
quarkus.tls.my-tls.key-store.pem.0.cert=./server-cert.pem
// after
quarkus.tls.my-tls.key-store.pem.0.key=/etc/app/certs/server-key.pem
quarkus.tls.my-tls.key-store.pem.0.cert=/etc/app/certs/server-cert.pem
Defensive patterns

Strategy: validation

Validate before calling

Stream.of(keyPath, certPath).forEach(p -> {
    File f = new File(p);
    if (!f.isFile()) throw new IllegalStateException("Missing PEM file: " + p);
    if (!f.canRead()) throw new IllegalStateException("Unreadable PEM file: " + p);
});

Try / catch

try {
    // use TLS config
} catch (IllegalStateException e) {
    if (e.getMessage().contains("cannot read the key/certificate files")) {
        log.errorf(e.getCause(), "PEM key/cert unreadable for %s", certName);
    }
}

Prevention

When it happens

Trigger: verifyPEMKeyStore calls PemKeyCertOptions.loadKeyStore(vertx) and an UncheckedIOException occurs: file missing, wrong path, no read permission, or content is not valid PEM while reading.

Common situations: Key/cert files absent in container image (paths valid locally but not in container); permissions changed by deployment tooling; key is encrypted PEM requiring a password not supported here; relative paths broken after working-directory change.

Understand the failure class

Related errors


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

Appendix: source

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

/**
 * A utility class to validate PEM key store and trust store configurations.
 */
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());

View on GitHub (pinned to e1c734241f)