From 4175cf66c944f50697b0fe2df1c378e059f347ca Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Mon, 9 Nov 2026 22:17:07 +1000 Subject: [PATCH] Fix: deleting a certificate now returns success even when some of its files can't be removed --- backend/internal/certificate.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index 327fe9919..b353c4838 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -538,16 +538,24 @@ const internalCertificate = { if (row.provider === "letsencrypt") { // Revoke the cert await internalCertificate.revokeLetsEncryptSsl(row); - // Certbot leaves the files behind when it can't revoke (e.g. a broken renewal config); remove them anyway - internalCertificate.removeLetsEncryptFiles(row.id); + // Certbot leaves the files behind when it can't revoke (e.g. a broken renewal config); remove them anyway. + // The row is already deleted and audited, so leftover files are logged, not thrown: + // an error here would report a completed delete as failed, and a retry would 404. + const leftover = internalCertificate.removeLetsEncryptFiles(row.id); + if (leftover.length) { + logger.warn( + `Certificate #${row.id} was deleted, but these files could not be removed and should be deleted by hand: ${leftover.join(", ")}`, + ); + } } return true; }, /** - * Removes a certificate's certbot files, as `certbot delete` would. + * Removes a certificate's certbot files, as `certbot delete` would. Never throws. * - * @param {Number} certificateId + * @param {Number} certificateId + * @returns {String[]} paths that could not be removed */ removeLetsEncryptFiles: (certificateId) => { const paths = [ @@ -565,11 +573,7 @@ const internalCertificate = { failed.push(p); } } - if (failed.length) { - throw new error.ValidationError( - `The certificate was removed from NPM, but these files could not be deleted: ${failed.join(", ")}. Delete them by hand.`, - ); - } + return failed; }, /**