{"record":{"id":"eabe9acf96cb833e","repo":"quarkusio/quarkus","slug":"the-file-path-does-not-contain-a-private-key-ty","errorCode":null,"errorMessage":"The file <path> does not contain a private key <type>","messagePattern":"The file <path> does not contain a private key <type>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/tls-registry/cli/src/main/java/io/quarkus/tls/cli/GenerateCertificateCommand.java","lineNumber":154,"sourceCode":"\n    private X509Certificate loadRootCertificate(File ca) throws Exception {\n        CertificateFactory cf = CertificateFactory.getInstance(\"X.509\");\n        try (FileInputStream fis = new FileInputStream(ca)) {\n            return (X509Certificate) cf.generateCertificate(fis);\n        }\n    }\n\n    private PrivateKey loadPrivateKey() throws Exception {\n        try (BufferedReader reader = new BufferedReader(new FileReader(Constants.PK_FILE));\n                PEMParser pemParser = new PEMParser(reader)) {\n            Object obj = pemParser.readObject();\n            if (obj instanceof KeyPair) {\n                return ((KeyPair) obj).getPrivate();\n            } else if (obj instanceof PrivateKeyInfo) {\n                JcaPEMKeyConverter converter = new JcaPEMKeyConverter();\n                return converter.getPrivateKey(((PrivateKeyInfo) obj));\n            } else {\n                throw new IllegalStateException(\n                        \"The file \" + Constants.PK_FILE.getAbsolutePath() + \" does not contain a private key \"\n                                + obj.getClass().getName());\n            }\n        }\n    }\n\n    private void createSignedCertificate(X509Certificate issuerCert,\n            PrivateKey issuerPrivateKey) throws Exception {\n        if (!Files.exists(directory)) {\n            Files.createDirectories(directory);\n        }\n        AUDIT.debug(\"Generating CA-signed certificate - name: \" + name + \", cn: \" + cn);\n        new CertificateGenerator(directory, renew).generate(new CertificateRequest()\n                .withName(name)\n                .withCN(cn)\n                .withPassword(password)\n                .withDuration(Duration.ofDays(365))\n                .withFormat(Format.PKCS12)","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/tls-registry/cli/src/main/java/io/quarkus/tls/cli/GenerateCertificateCommand.java#L136-L172","documentation":"When generating a CA-signed certificate, the CLI loads the certificate authority private key from a fixed file (Constants.PK_FILE, typically the CA's PEM private key) using BouncyCastle's PEMParser. If the first PEM object parsed from that file is neither a KeyPair nor a PrivateKeyInfo (e.g. it is a certificate, an encrypted private key, or a public key), loadPrivateKey throws this IllegalStateException naming the actual parsed Java class. It is a guard against using a file that does not hold a usable CA private key.","triggerScenarios":"Running the CA-signed certificate generation command (caPrivateKey path) when the CA key file at Constants.PK_FILE contains a PEM object of another type — most commonly an X509Certificate instead of the key, an encrypted PEM (PEMEncryptedKeyPair / PEMEncryptedPrivateKey) which parses as neither branch, or a SubjectPublicKeyInfo.","commonSituations":"Swapped files: user copied the CA certificate (.crt/.pem) over the key file path; a PKCS#8 key protected with a passphrase (encrypted PEM not decryptable here); keys regenerated by another tool in a format PEMParser reads as a non-key object; empty or truncated key file leaving a leftover certificate object.","solutions":["Verify the file at the reported path actually contains the CA private key PEM block (BEGIN PRIVATE KEY / BEGIN RSA PRIVATE KEY / BEGIN EC PRIVATE KEY), not the certificate","If the CA key is encrypted, decrypt it first (openssl pkcs8 -topk8 -nocrypt -in ca.key -out ca-decrypted.key) and point the tooling at the unencrypted key","Restore the correct key file (re-export from your keystore or regenerate the CA if lost, then re-issue certificates)","Re-run the command; the exception message prints the parsed class name (e.g. org.bouncycastle.asn1.x509.Certificate) telling you exactly what the file contains"],"exampleFix":"// before: file contains the CA certificate, PEMParser reads an X509Certificate -> IllegalStateException\nopenssl x509 -in ca.pem -out ca-wrong.pem   # wrong content at key path\n\n// after: place the unencrypted private key PEM where the CLI expects it\nopenssl pkcs8 -topk8 -nocrypt -in ca-encrypted.key -out ca.key\n","handlingStrategy":"validation","validationCode":"import org.bouncycastle.openssl.PEMParser;\nimport java.io.*;\n\nstatic boolean isPrivateKeyPem(File keyFile) {\n    if (keyFile == null || !keyFile.isFile()) return false;\n    try (PEMParser p = new PEMParser(new FileReader(keyFile))) {\n        Object obj = p.readObject();\n        return obj instanceof java.security.KeyPair\n            || obj instanceof org.bouncycastle.asn1.pkcs.PrivateKeyInfo;\n    } catch (IOException e) {\n        return false;\n    }\n}\n// call before generating: if (!isPrivateKeyPem(Constants.PK_FILE)) throw ...\n","typeGuard":"static boolean isPemPrivateKey(Object pemObject) {\n    return pemObject instanceof java.security.KeyPair\n        || pemObject instanceof org.bouncycastle.asn1.pkcs.PrivateKeyInfo;\n}\n","tryCatchPattern":"try {\n    PrivateKey key = loadPrivateKey();\n} catch (IllegalStateException e) {\n    // e.getMessage() names the offending class; check the file content\n    throw new IllegalArgumentException(\n        \"CA key file is not a private key PEM: \" + e.getMessage(), e);\n}","preventionTips":["Keep CA certificate and CA key files in clearly named separate files (ca.crt vs ca.key) and never overwrite one with the other","Store unencrypted PKCS#8 PEM keys for automated tooling; decrypt passphrase-protected keys before use","Validate PEM file headers (grep \"BEGIN PRIVATE KEY\") before handing a file to the generator","After regenerating or exporting CA material, re-run a content check before issuing certificates"],"tags":["tls","pem","private-key","bouncycastle","certificate-authority"],"backgroundTag":"invalid-private-key-file","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}