From a4e9e987393cdd68720a9d92de10ca71ec19ca2b Mon Sep 17 00:00:00 2001 From: automated-signal <37887102+automated-signal@users.noreply.github.com> Date: Thu, 12 Feb 2026 10:15:34 -0600 Subject: [PATCH] Better accounting of orphaned attachments Co-authored-by: trevor-signal <131492920+trevor-signal@users.noreply.github.com> --- app/attachment_channel.main.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/attachment_channel.main.ts b/app/attachment_channel.main.ts index cf35ff6296..24c059945a 100644 --- a/app/attachment_channel.main.ts +++ b/app/attachment_channel.main.ts @@ -19,6 +19,8 @@ import z from 'zod'; import GrowingFile from 'growing-file'; import lodash from 'lodash'; import { pathExists } from 'fs-extra'; +import pMap from 'p-map'; +import { access } from 'node:fs/promises'; import { type DecryptAttachmentToSinkOptionsType, @@ -462,6 +464,22 @@ function deleteOrphanedAttachments({ `cleanupOrphanedAttachments: ${totalAttachmentsFound} attachments and \ ${totalDownloadsFound} downloads found on disk` ); + const attachmentsFolder = getAttachmentsPath(userDataPath); + + // It's possible that messages and attachments have been deleted since we first + // checked the contents of the attachments folder, so for better accounting, we + // check once more that they still exist. + await pMap( + orphanedAttachments, + async path => { + try { + await access(join(attachmentsFolder, path)); + } catch (e) { + orphanedAttachments.delete(path); + } + }, + { concurrency: 20 } + ); if (orphanedAttachments.size > 0) { log.error(`${orphanedAttachments.size} orphaned attachment(s) found`);