{"record":{"id":"db288b812641fe2e","repo":"quarkusio/quarkus","slug":"failure-to-copy-certificate-pem-ex-getmessage","errorCode":null,"errorMessage":"Failure to copy certificate pem: + ex.getMessage()","messagePattern":"Failure to copy certificate pem: \\+ ex\\.getMessage\\(\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/tls-registry/cli/src/main/java/io/quarkus/tls/cli/letsencrypt/LetsEncryptHelpers.java","lineNumber":206,"sourceCode":"            certChainAndPrivateKey = acmeClient.obtainCertificateChain(acmeAccount, staging, domain);\n            AUDIT.info(\"Certificate chain obtained successfully - domain: \" + domain + \", chain-length: \"\n                    + certChainAndPrivateKey.getCertificateChain().length);\n        } catch (AcmeException t) {\n            AUDIT.error(\"Failed to obtain certificate - domain: \" + domain + \", staging: \" + staging, t);\n            throw new RuntimeException(\"Failed to obtain certificate: \" + t.getMessage(), t);\n        }\n        LOGGER.info(\"\\uD83D\\uDD35 Certificate and private key issued, converting them to PEM files\");\n\n        AUDIT.info(\"Writing certificate to: \" + certChainPemLoc.getAbsolutePath());\n        AUDIT.info(\"Writing private key to: \" + privateKeyPemLoc.getAbsolutePath());\n\n        try {\n            LetsEncryptHelpers.writePrivateKeyAndCertificateChainsAsPem(certChainAndPrivateKey.getSigningKey(),\n                    certChainAndPrivateKey.getCertificateChain(), privateKeyPemLoc, certChainPemLoc);\n        } catch (Exception ex) {\n            AUDIT.error(\"Failed to write certificate files - cert: \" + certChainPemLoc + \", key: \"\n                    + privateKeyPemLoc, ex);\n            throw new RuntimeException(\"Failure to copy certificate pem: \" + ex.getMessage(), ex);\n        }\n    }\n\n    private static AcmeAccount getAccount(File letsEncryptPath, String acmeServerUrl, String acmeStagingServerUrl) {\n        LOGGER.debugf(\"Getting account from %s\", letsEncryptPath);\n\n        // Use defaults if not specified\n        String serverUrl = acmeServerUrl != null ? acmeServerUrl\n                : DEFAULT_ACME_URL;\n        String stagingServerUrl = acmeStagingServerUrl != null ? acmeStagingServerUrl\n                : DEFAULT_ACME_STAGING_URL;\n\n        JsonObject json = readAccountJson(letsEncryptPath);\n        AcmeAccount.Builder builder = AcmeAccount.builder().setTermsOfServiceAgreed(true)\n                .setServerUrl(serverUrl)\n                .setStagingServerUrl(stagingServerUrl);\n\n        String keyAlgorithm = json.getString(\"key-algorithm\");","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/tls-registry/cli/src/main/java/io/quarkus/tls/cli/letsencrypt/LetsEncryptHelpers.java#L188-L224","documentation":"After the certificate chain is obtained, issueCertificate writes the private key and certificate chain as PEM files via writePrivateKeyAndCertificateChainsAsPem. Any exception during this conversion/writing step is wrapped in this RuntimeException (message includes the underlying ex.getMessage(), despite the misplaced quote in the literal). It indicates a local I/O or encoding failure, not an ACME problem.","triggerScenarios":"Calling issueCertificate/renewCertificate when the target certChainPemLoc or privateKeyPemLoc files/directories cannot be written — bad path, missing parent directory, permissions — or the key/certificate cannot be PEM-encoded.","commonSituations":"Certificate output directory does not exist; the process lacks write permission to the target path; disk full; the existing target file is locked or read-only.","solutions":["Ensure the parent directories of certChainPemLoc and privateKeyPemLoc exist and are writable","Check file permissions on the existing pem files (they may be read-only or owned by another user)","Free disk space if the filesystem is full","Inspect the wrapped cause in the stack trace for the exact write/encode failure"],"exampleFix":"// before\nFile cert = new File(\"/missing/dir/cert.pem\");\nLetsEncryptHelpers.issueCertificate(..., cert, key, ...); // RuntimeException: Failure to copy certificate pem\n// after\nnew File(\"/missing/dir\").mkdirs();\nLetsEncryptHelpers.issueCertificate(..., cert, key, ...);","handlingStrategy":"validation","validationCode":"File cert = certChainPemLoc, key = privateKeyPemLoc;\nfor (File f : new File[]{cert, key}) {\n    File parent = f.getAbsoluteFile().getParentFile();\n    if (parent == null || (!parent.exists() && !parent.mkdirs()) || !parent.canWrite()) {\n        throw new IllegalStateException(\"Cannot write to directory: \" + parent);\n    }\n    if (f.exists() && !f.canWrite()) throw new IllegalStateException(\"File not writable: \" + f);\n}","typeGuard":null,"tryCatchPattern":"try {\n    LetsEncryptHelpers.issueCertificate(acmeClient, letsEncryptPath, staging, domain, keyLoc, certLoc);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Failure to copy certificate pem:\")) {\n        throw new IllegalStateException(\"Could not write cert/key to \" + certLoc + \"/\" + keyLoc + \": \" + e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Create output directories before issuing certificates","Check write permissions on cert/key target files and directories","Ensure sufficient disk space before renewals","Avoid running as a user that cannot overwrite existing pem files"],"tags":["io","filesystem","pem","certificate"],"backgroundTag":"file-write-permission-denied","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"}