eclipse-vertx/vert.x · error · RuntimeException
Missing -----BEGIN PRIVATE KEY----- or -----BEGIN RSA PRIVAT
Error message
Missing -----BEGIN PRIVATE KEY----- or -----BEGIN RSA PRIVATE KEY----- or -----BEGIN EC PRIVATE KEY----- delimiter
What it means
Same site family as the empty-message variant: loadPrivateKey() found no PEM private key block in the provided buffer and throws because the parsed key list is empty. It explicitly names the three delimiters it supports: BEGIN PRIVATE KEY, BEGIN RSA PRIVATE KEY, BEGIN EC PRIVATE KEY.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/net/impl/KeyStoreHelper.java:322
case "PRIVATE KEY":
// in PKCS#8 the key algorithm is indicated at the beginning of the ASN.1 structure
// so we can use the corresponding key factory once we know the algorithm name
String algorithm = PrivateKeyParser.getPKCS8EncodedKeyAlgorithm(content);
if (rsaKeyFactory.getAlgorithm().equals(algorithm)) {
return Collections.singletonList(rsaKeyFactory.generatePrivate(new PKCS8EncodedKeySpec(content)));
} else if (ecKeyFactory != null && ecKeyFactory.getAlgorithm().equals(algorithm)) {
return Collections.singletonList(ecKeyFactory.generatePrivate(new PKCS8EncodedKeySpec(content)));
}
// fall through if ECC is not supported by JVM
default:
return Collections.emptyList();
}
} catch (InvalidKeySpecException e) {
throw new VertxException(e);
}
});
if (pems.isEmpty()) {
throw new RuntimeException("Missing -----BEGIN PRIVATE KEY----- or -----BEGIN RSA PRIVATE KEY----- or -----BEGIN EC PRIVATE KEY----- delimiter");
}
return pems.get(0);
}
private static KeyFactory getECKeyFactory() {
try {
return KeyFactory.getInstance("EC");
} catch (NoSuchAlgorithmException e) {
// support for ECC is not mandatory in JVM
return null;
}
}
public static KeyStore loadCA(Stream<Buffer> certValues) throws Exception {
final KeyStore keyStore = createEmptyKeyStore();
keyStore.load(null, null);
int count = 0;
Iterable<Buffer> iterable = certValues::iterator;View on GitHub (pinned to fb308bd8c3)
Solutions
- Confirm the file contains -----BEGIN PRIVATE KEY----- (PKCS#8), -----BEGIN RSA PRIVATE KEY-----, or -----BEGIN EC PRIVATE KEY-----.
- Convert PKCS#1 to PKCS#8 with: openssl pkcs8 -topk8 -nocrypt -in rsakey.pem -out pkcs8key.pem.
- Decrypt encrypted keys first (remove ENCRYPTED PRIVATE KEY / Proc-Type headers) or load them via a JKS/PKCS12 keystore instead.
- Ensure the key path/Buffer is correct and not the certificate file.
Example fix
// before
options.setKeyPath("chain-ca.pem"); // no key block
// after
options.setKeyPath("server.key"); // -----BEGIN PRIVATE KEY----- Defensive patterns
Strategy: validation
Validate before calling
String pem = Files.readString(Path.of(keyPath));
boolean ok = pem.lines().anyMatch(l -> l.startsWith("-----BEGIN") && l.contains("PRIVATE KEY"));
if (!ok) throw new IllegalStateException(keyPath + " has no private key PEM block"); Type guard
boolean hasPrivateKeyBlock(String s) {
return s != null && s.contains("-----BEGIN PRIVATE KEY-----") ||
s != null && s.contains("-----BEGIN RSA PRIVATE KEY-----") ||
s != null && s.contains("-----BEGIN EC PRIVATE KEY-----");
} Prevention
- Convert all keys to unencrypted PKCS#8 format once, at provisioning time
- Never pass certificate chains or CA bundles as the key option
- Log/verify the first line of the key file at startup in dev mode
- Document key format requirements in your deployment config schema
When it happens
Trigger: keyCertOptions.setKeyPath/setKeyValue receiving a PEM buffer whose only blocks are certificates, or whose key block type is unsupported (e.g. ENCRYPTED PRIVATE KEY), or a truncated file with BEGIN but no key data.
Common situations: Swapping cert and key paths; using an encrypted PKCS#8 key with a password the parser cannot supply; concatenating only the CA chain into the key option.
Related errors
- Missing -----END ----- delimiter
- Empty pem file
- Missing -----BEGIN CERTIFICATE----- delimiter
- Failed to initialize the keystore
- Unsupported algorithm identifier
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/23a5699f9fb7d7d1.
Report an issue: GitHub.