apache/pulsar · error · CertificateException

jcaProvider='${providerName}' does not supply CertificateFac

Error message

jcaProvider='${providerName}' does not supply CertificateFactory type '${type}'. Types this provider registers: ${registeredTypes}. Unset jcaProvider, or pin a provider that supplies X.509 certificates.

What it means

JcaKeyStores.certificateFactory(type, jcaProvider) pins CertificateFactory creation to a given Provider and first checks provider.getService("CertificateFactory", type). If the pinned provider does not register that certificate type (typically X.509), it throws CertificateException naming the provider and its registered types.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/tls/JcaKeyStores.java:115

        return KeyStore.getInstance(type, jcaProvider);
    }

    /**
     * Create an X.509 {@link CertificateFactory}, from {@code jcaProvider} when one is pinned.
     *
     * @param type        the certificate type (in practice {@code X.509})
     * @param jcaProvider the pinned JCA provider, or {@code null} for the JVM provider search order
     * @return the certificate factory
     * @throws CertificateException if the type is unavailable — including when a pinned provider does not
     *                              register it
     */
    public static CertificateFactory certificateFactory(String type, Provider jcaProvider)
            throws CertificateException {
        if (jcaProvider == null) {
            return CertificateFactory.getInstance(type);
        }
        if (jcaProvider.getService("CertificateFactory", type) == null) {
            throw new CertificateException("jcaProvider='" + jcaProvider.getName() + "' does not supply "
                    + "CertificateFactory type '" + type + "'. Types this provider registers: "
                    + registeredTypes(jcaProvider, "CertificateFactory") + ". Unset jcaProvider, or pin a provider "
                    + "that supplies X.509 certificates.");
        }
        return CertificateFactory.getInstance(type, jcaProvider);
    }

    /**
     * Choose the store type for a process-local in-memory carrier keystore: with no pinned provider the
     * caller's current default ({@code defaultType}, i.e. today's behaviour), otherwise the first
     * {@link #IN_MEMORY_STORE_TYPE_PREFERENCE preferred} type the pinned provider actually registers.
     *
     * @param jcaProvider the pinned JCA provider, or {@code null}
     * @param defaultType the type to use when no provider is pinned
     * @return the carrier store type
     * @throws KeyStoreException if the pinned provider registers none of the preferred carrier types
     */
    public static String inMemoryStoreType(Provider jcaProvider, String defaultType) throws KeyStoreException {

View on GitHub (pinned to 820761864e)

Solutions

  1. Pin a provider that supplies X.509 CertificateFactory services (e.g. BouncyCastle BC/BCFIPS with the cert-path services registered)
  2. Pass null as jcaProvider to use the JDK default provider
  3. Register the missing service in your custom provider configuration

Example fix

// before
CertificateFactory cf = JcaKeyStores.certificateFactory("X.509", bcFipsJcaProvider); // provider lacks X.509
// after
CertificateFactory cf = JcaKeyStores.certificateFactory("X.509", null); // or use a provider registering X.509
Defensive patterns

Strategy: validation

Validate before calling

Provider p = ...;
if (p != null && p.getService("CertificateFactory", "X.509") == null) {
    throw new IllegalArgumentException("Provider " + p.getName() + " lacks CertificateFactory X.509");
}

Type guard

boolean providerHasX509CertFactory(Provider p) { return p == null || p.getService("CertificateFactory", "X.509") != null; }

Try / catch

try { return JcaKeyStores.certificateFactory("X.509", provider); } catch (CertificateException e) { log.error("X.509 CertificateFactory unavailable in provider {}: {}", provider, e.getMessage()); throw e; }

Prevention

When it happens

Trigger: Calling certificateFactory("X.509", provider) where the provider (e.g. a JCA-only BCFIPS provider without the X.509 CertFactory service, or a narrowly scoped provider) lacks the CertificateFactory.X.509 service.

Common situations: FIPS TLS setup where the jcaProvider is pinned but does not supply X.509 certificate parsing; PEM certificate loading (PemReader) with a mis-pinned provider.

Understand the failure class

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/ed04b85b5e68dd83. Report an issue: GitHub.