apache/pulsar · error · IllegalArgumentException
No java.security.Provider named '${name}' could be resolved
Error message
No java.security.Provider named '${name}' could be resolved via Security.getProvider(...) or via ServiceLoader (META-INF/services/java.security.Provider) on the application class loader. Ensure the provider is on the classpath and registered — a JSSE (SSLContext) provider such as BCJSSE for jsseProvider (which additionally requires the bctls jar on the classpath), or a JCA (KeyStore/CertificateFactory) provider such as BCFIPS for jcaProvider. What it means
JcaProviders.resolveNamedProvider(name) resolves a named java.security.Provider first via Security.getProvider(name), then via ServiceLoader on META-INF/services/java.security.Provider, and finally via known BouncyCastle aliases. If nothing resolves, it throws IllegalArgumentException — a misconfigured provider must fail loudly rather than silently falling back to the default.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/tls/JcaProviders.java:433
+ "named JCA provider");
continue;
}
if (name.equals(provider.getName())) {
log.debug().attr("provider", name).log("Resolved JCA provider via ServiceLoader");
return provider;
}
}
// 3. BouncyCastle's JSSE provider is invisible to both steps above until someone registers it —
// bctls ships no services entry — so register it from the classpath on demand when it is the name
// being pinned. See bouncyCastleJsseProvider() for why it cannot just be default-constructed.
if (BC_JSSE.equals(name)) {
Optional<ResolvedBouncyCastleProvider> jsse = bouncyCastleJsseProvider();
if (jsse.isPresent()) {
return jsse.get().provider();
}
}
// 4. Fail loudly — a misconfigured provider must not silently default.
throw new IllegalArgumentException("No java.security.Provider named '" + name + "' could be resolved via "
+ "Security.getProvider(...) or via ServiceLoader (META-INF/services/java.security.Provider) on the "
+ "application class loader. Ensure the provider is on the classpath and registered — a JSSE "
+ "(SSLContext) provider such as BCJSSE for jsseProvider (which additionally requires the bctls jar "
+ "on the classpath), or a JCA (KeyStore/CertificateFactory) "
+ "provider such as BCFIPS for jcaProvider.");
}
/**
* Resolve a security {@link Provider} by name, falling back to the default {@code TLS}
* {@code SSLContext} provider when the name is blank or unknown.
*/
static Provider resolveProvider(String providerName) throws NoSuchAlgorithmException {
Provider provider = null;
if (!StringUtils.isEmpty(providerName)) {
provider = Security.getProvider(providerName);
}
if (provider == null) {View on GitHub (pinned to 820761864e)
Solutions
- Add the provider jar to the classpath (bc-fips for BCFIPS; bcpkix/bctls for BCJSSE)
- Register it programmatically with Security.addProvider(new BouncyCastleFipsProvider()) or in java.security config
- Correct the provider name spelling in the configuration to match Provider.getName()
- Verify ServiceLoader entries survive shading/build repackaging
Example fix
// before (config) tlsJsseProviderName=BCJSSE // bctls jar missing // after // add bctls + bc-fips jars to classpath, then: Security.addProvider(new org.bouncycastle.jsse.provider.BouncyCastleJsseProvider()); tlsJsseProviderName=BCJSSE
Defensive patterns
Strategy: validation
Validate before calling
String name = "BCFIPS";
Provider p = Security.getProvider(name);
if (p == null) {
p = ServiceLoader.load(java.security.Provider.class).stream()
.map(Provider::getName).filter(name::equals).findFirst().orElse(null);
}
if (p == null) throw new IllegalStateException("Provider " + name + " not on classpath/registered"); Type guard
java.util.Optional<Provider> findProvider(String name) { Provider p = Security.getProvider(name); return p != null ? java.util.Optional.of(p) : ServiceLoader.load(java.security.Provider.class).stream().filter(x -> x.getName().equals(name)).findFirst(); } Try / catch
try { Provider p = JcaProviders.resolveNamedProvider(name); } catch (IllegalArgumentException e) { log.error("TLS provider '{}' unresolved — check classpath and Security.addProvider: {}", name, e.getMessage()); throw e; } Prevention
- Add the provider jars (bc-fips, bcpkix-fips, bctls-fips) to the runtime classpath
- Register providers in java.security config or Security.addProvider at startup
- Verify shaded/fat jars retain META-INF/services/java.security.Provider entries
- Fail fast with a startup self-check that resolves all configured provider names
- Match configured names exactly to Provider.getName() (e.g. 'BCFIPS', 'BCJSSE')
When it happens
Trigger: Configuring a provider name (e.g. jsseProvider=BCJSSE or jcaProvider=BCFIPS) when: the jar is not on the classpath; the provider was never registered via Security.addProvider / security properties; the name is misspelled; or for BCJSSE the bctls jar is missing so the SSLContext provider cannot be found.
Common situations: FIPS-mode broker/client startup with tls provider settings pointing at BouncyCastle that isn't packaged; typos in provider names in pulsar config files; fat-jar shading dropping META-INF/services entries.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- certFilePath must not be null
- keyFilePath must not be null
- Passed in parameter empty. KEYSTORE_PATH: ${keyStorePath} KE
- jcaProvider='${providerName}' does not supply KeyStore type
- jcaProvider='${providerName}' does not supply CertificateFac
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/4c7c3116174301a4.
Report an issue: GitHub.