quarkusio/quarkus · error · IOException
Invalid PEM file: No PEM content found.
Error message
Invalid PEM file: No PEM content found.
What it means
loadCertificateFromPEM parses a PEM file using BouncyCastle's PemReader. If the file contains no recognizable PEM block (a line like '-----BEGIN ...-----'), readPemObject() returns null and the method throws this IOException. It signals the file is not a valid PEM-encoded certificate.
Source
Thrown at extensions/tls-registry/cli/src/main/java/io/quarkus/tls/cli/letsencrypt/LetsEncryptHelpers.java:69
AUDIT.debug("Writing certificate chain to file: " + certificateChainFile.getAbsolutePath());
if (chain.length == 1) {
CertificateUtils.writeCertificateToPEM(chain[0], certificateChainFile);
return;
}
// For some reason the method from CertificateUtils distinguishes the first certificate and the rest of the chain
X509Certificate[] restOfTheChain = new X509Certificate[chain.length - 1];
System.arraycopy(chain, 1, restOfTheChain, 0, chain.length - 1);
CertificateUtils.writeCertificateToPEM(chain[0], certificateChainFile, restOfTheChain);
}
public static X509Certificate loadCertificateFromPEM(String pemFilePath) throws IOException, CertificateException {
try (PemReader pemReader = new PemReader(new FileReader(pemFilePath))) {
PemObject pemObject = pemReader.readPemObject();
if (pemObject == null) {
throw new IOException("Invalid PEM file: No PEM content found.");
}
byte[] content = pemObject.getContent();
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
return (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(content));
}
}
public static String createAccount(AcmeClient acmeClient,
String letsEncryptPath,
boolean staging,
String contactEmail,
String acmeServerUrl,
String acmeStagingServerUrl) {
LOGGER.infof("\uD83D\uDD35 Creating %s ACME account", (staging ? "staging" : "production"));
// Use defaults if not specified
String serverUrl = acmeServerUrl != null ? acmeServerUrl
: DEFAULT_ACME_URL;View on GitHub (pinned to e1c734241f)
Solutions
- Open the file and confirm it contains '-----BEGIN CERTIFICATE-----' and '-----END CERTIFICATE-----' lines
- Convert a DER certificate to PEM: openssl x509 -inform der -in cert.der -out cert.pem
- Re-export/re-download the certificate in PEM (base64) format from your CA
- Verify the file path points to the actual certificate, not a keystore or private key file
- Check the file is not empty or truncated (file size, cat the file)
Example fix
// before (file is DER)
X509Certificate cert = LetsEncryptHelpers.loadCertificateFromPEM("cert.der");
// after: convert first
// openssl x509 -inform der -in cert.der -out cert.pem
X509Certificate cert = LetsEncryptHelpers.loadCertificateFromPEM("cert.pem"); Defensive patterns
Strategy: validation
Validate before calling
boolean isPem(String path) throws IOException {
String content = Files.readString(Paths.get(path));
return content.contains("-----BEGIN CERTIFICATE-----") && content.contains("-----END CERTIFICATE-----");
}
if (!isPem(pemFilePath)) throw new IllegalArgumentException("Not a PEM certificate: " + pemFilePath);
X509Certificate cert = LetsEncryptHelpers.loadCertificateFromPEM(pemFilePath); Type guard
boolean looksLikePem(byte[] bytes) {
String head = new String(bytes, 0, Math.min(bytes.length, 64), StandardCharsets.US_ASCII).trim();
return head.startsWith("-----BEGIN ");
} Try / catch
try {
X509Certificate cert = LetsEncryptHelpers.loadCertificateFromPEM(path);
} catch (IOException | CertificateException e) {
// e.getMessage() == "Invalid PEM file: No PEM content found."
throw new IllegalArgumentException("File is not PEM-encoded: " + path + ". Convert with: openssl x509 -inform der -in file -out file.pem", e);
} Prevention
- Always verify the file starts with '-----BEGIN' before parsing
- Use 'openssl x509 -in file -text -noout' to sanity-check certificates before use
- Never rename DER/keystore files to .pem without converting them
- Validate downloaded files are actual certificates, not HTML error pages
When it happens
Trigger: Calling LetsEncryptHelpers.loadCertificateFromPEM with a path to a file whose content has no '-----BEGIN...'/'-----END...' delimiters — e.g. a DER-encoded cert, a private key in another format, an empty file, or an HTML error page saved as .pem.
Common situations: Downloading a certificate and accidentally saving the HTML error response; exporting a certificate as DER (.der/.crt binary) but naming it .pem; a truncated or corrupted download; pointing the tool at a PKCS#12/JKS keystore instead of a PEM file.
Related errors
- Failure to copy certificate pem: + ex.getMessage()
- No key/certificate pair configured for certificate '${name}'
- Invalid key/certificate pair configuration for certificate '
- Invalid key/certificate pair configuration for certificate '
- Invalid PEM trusted certificates configuration for certifica
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/753ae4bdc21a26aa.
Report an issue: GitHub.