From 80ae204cbe0d0f21368d3cab2494dc57245fe770 Mon Sep 17 00:00:00 2001 From: Marco Beretta <81851188+berry-13@users.noreply.github.com> Date: Sun, 5 Jul 2026 03:11:46 +0200 Subject: [PATCH] fix: enforce tag retention before the rename commits PUT /api/tags/:tag renamed the tag first and ran the forced-retention cascade with the new tag afterwards. A cascade failure returned 500 with the rename already committed, and a retried PUT /:oldTag hit the 404 path because the old tag no longer exists, so the tagged conversations' messages, shares, and files could never be backfilled. Run the cascade with the old tag before the rename, mirroring the DELETE route: the old tag selects the same conversations the renamed tag will carry, enforcing on a nonexistent tag is a no-op, and a failed rename now retries cleanly with retention already applied. --- api/server/routes/tags.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/api/server/routes/tags.js b/api/server/routes/tags.js index d4584a5212..6fe79da8c5 100644 --- a/api/server/routes/tags.js +++ b/api/server/routes/tags.js @@ -96,10 +96,16 @@ router.post('/', configMiddleware, async (req, res) => { router.put('/:tag', configMiddleware, async (req, res) => { try { const decodedTag = decodeURIComponent(req.params.tag); + /** + * Enforce retention with the old tag before the rename commits. The rename rewrites the + * conversations' tag entries, so a cascade failure afterwards would 500 while a retried + * PUT /:oldTag hits the 404 path (the old tag no longer exists) and the affected chats + * never convert. The old tag selects the same conversations the renamed tag will carry, + * and enforcing on a nonexistent tag is a no-op, so a failed rename retries cleanly. + */ + await enforceForcedRetentionForTag(req, decodedTag, 'PUT /api/tags/:tag'); const tag = await updateConversationTag(req.user.id, decodedTag, req.body); if (tag) { - const renamedTag = typeof req.body?.tag === 'string' ? req.body.tag : decodedTag; - await enforceForcedRetentionForTag(req, renamedTag, 'PUT /api/tags/:tag'); res.status(200).json(tag); } else { res.status(404).json({ error: 'Tag not found' });