From aebdbc1687dfef460489bd3bbd229d8499302e3b Mon Sep 17 00:00:00 2001 From: Matthieu MALVACHE Date: Thu, 2 Oct 2025 13:15:40 +0200 Subject: [PATCH] fix: Capture latest draft ID after save to prevent race condition When sending an email with attachments, saveDraft() would destroy+create the draft (generating a new ID), but handleSend() was using the old ID from React state which hadn't updated yet. This caused "notFound" errors. Fixed by making saveDraft() return the draft ID and using it directly in handleSend() instead of relying on async state updates. --- components/email/email-composer.tsx | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/components/email/email-composer.tsx b/components/email/email-composer.tsx index 3ce8dfc..a516c86 100644 --- a/components/email/email-composer.tsx +++ b/components/email/email-composer.tsx @@ -150,8 +150,8 @@ export function EmailComposer({ }; // Auto-save draft functionality - const saveDraft = async () => { - if (!client) return; + const saveDraft = async (): Promise => { + if (!client) return null; const toAddresses = to.split(",").map(e => e.trim()).filter(Boolean); const ccAddresses = cc.split(",").map(e => e.trim()).filter(Boolean); @@ -159,7 +159,7 @@ export function EmailComposer({ // Only save if there's some content if (!toAddresses.length && !subject && !body) { - return; + return null; } // Prepare attachments for draft @@ -177,7 +177,7 @@ export function EmailComposer({ // Only save if data has changed if (currentData === lastSavedDataRef.current) { - return; + return draftId; } setSaveStatus('saving'); @@ -199,10 +199,13 @@ export function EmailComposer({ // Reset status after 2 seconds setTimeout(() => setSaveStatus('idle'), 2000); + + return savedDraftId; } catch (error) { console.error('Failed to save draft:', error); setSaveStatus('error'); setTimeout(() => setSaveStatus('idle'), 3000); + return null; } }; @@ -237,10 +240,15 @@ export function EmailComposer({ const bccAddresses = bcc.split(",").map(e => e.trim()).filter(Boolean); if (toAddresses.length > 0 && subject && body) { - // Wait for any pending auto-save to complete + // Wait for any pending auto-save to complete and get the latest draft ID + let finalDraftId = draftId; if (saveTimeoutRef.current) { clearTimeout(saveTimeoutRef.current); - await saveDraft(); + // saveDraft returns the new draft ID after destroy+create + const savedId = await saveDraft(); + if (savedId) { + finalDraftId = savedId; + } } onSend?.({ @@ -249,7 +257,7 @@ export function EmailComposer({ bcc: bccAddresses, subject, body, - draftId: draftId || undefined, + draftId: finalDraftId || undefined, }); // Reset form