spring-projects/spring-boot · critical · IllegalStateException
Unable to get X.509 certificate factory
Error message
Unable to get X.509 certificate factory
What it means
PemCertificateParser.getCertificateFactory calls CertificateFactory.getInstance("X.509") and wraps any CertificateException in IllegalStateException. Like SHA-256, the X.509 certificate factory is mandatory in every Java SE implementation, so this only fires on a non-compliant or stripped runtime that does not register the sun.security.x509 provider.
Source
Thrown at buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PemCertificateParser.java:77
*/
@Contract("!null -> !null")
static @Nullable List<X509Certificate> parse(@Nullable String text) {
if (text == null) {
return null;
}
CertificateFactory factory = getCertificateFactory();
List<X509Certificate> certs = new ArrayList<>();
readCertificates(text, factory, certs::add);
Assert.state(!CollectionUtils.isEmpty(certs), "Missing certificates or unrecognized format");
return List.copyOf(certs);
}
private static CertificateFactory getCertificateFactory() {
try {
return CertificateFactory.getInstance("X.509");
}
catch (CertificateException ex) {
throw new IllegalStateException("Unable to get X.509 certificate factory", ex);
}
}
private static void readCertificates(String text, CertificateFactory factory, Consumer<X509Certificate> consumer) {
try {
Matcher matcher = PATTERN.matcher(text);
while (matcher.find()) {
String encodedText = matcher.group(1);
byte[] decodedBytes = decodeBase64(encodedText);
ByteArrayInputStream inputStream = new ByteArrayInputStream(decodedBytes);
while (inputStream.available() > 0) {
consumer.accept((X509Certificate) factory.generateCertificate(inputStream));
}
}
}
catch (CertificateException ex) {
throw new IllegalStateException("Error reading certificate: " + ex.getMessage(), ex);
}View on GitHub (pinned to 270dfe353f)
Solutions
- Run on a stock OpenJDK distribution where X.509 is always available.
- If using jlink, do not exclude the certificate-related providers.
- Smoke-test: `CertificateFactory.getInstance("X.509")` in jshell.
Defensive patterns
Strategy: validation
Validate before calling
// Startup smoke-test for the X.509 certificate factory
try {
CertificateFactory.getInstance("X.509");
} catch (CertificateException e) {
throw new IllegalStateException(
"This JRE does not provide an X.509 certificate factory; use a stock OpenJDK.", e);
} Prevention
- Run on a stock OpenJDK; X.509 is mandatory.
- When building a custom jlink image, do not exclude certificate providers.
- Add a smoke-test for CertificateFactory.getInstance("X.509") to your image build.
When it happens
Trigger: CertificateFactory.getInstance("X.509") throws CertificateException because no provider offers the X.509 factory; caught at line 76.
Common situations: A jlink-built runtime that excluded certificate providers; a FIPS-hardened or policy-restricted JVM; a non-standard JVM with an incomplete java.security.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- SHA-256 is not available
- Error adding certificates to KeyStore: {}
- Error reading certificate: {}
- 'value' must contain a well formed version number [{}]
- Docker API version must be at least %s to support this featu
AI-assisted analysis of spring-projects/spring-boot@270dfe353f (2026-08-11).
Data as JSON: /api/errors/a62132d232164b6f.
Report an issue: GitHub.