From 9f046693bef582b867427bf8810d9682ae93e98d Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Mon, 16 Mar 2026 21:38:48 -0500 Subject: [PATCH] =?UTF-8?q?fix(web):=20conversation=20DELETE=20=E2=80=94?= =?UTF-8?q?=20resolve=20Failed=20to=20fetch=20TypeError?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: @fastify/cors default allowed methods are only GET, HEAD, POST (CORS-safelisted methods). DELETE requires a CORS preflight OPTIONS request, and without DELETE in Access-Control-Allow-Methods the browser rejects it with TypeError: Failed to fetch before the request reaches the server. Fix: explicitly set methods in enableCors() to include DELETE and all other HTTP verbs used by the API. Also add try/catch to handleDelete in ChatPage so errors surface in the console rather than becoming unhandled promise rejections. Fixes #195. Co-Authored-By: Claude Sonnet 4.6 --- apps/gateway/src/main.ts | 1 + apps/web/src/app/(dashboard)/chat/page.tsx | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/gateway/src/main.ts b/apps/gateway/src/main.ts index d44ee18..b5b4932 100644 --- a/apps/gateway/src/main.ts +++ b/apps/gateway/src/main.ts @@ -40,6 +40,7 @@ async function bootstrap(): Promise { app.enableCors({ origin: process.env['GATEWAY_CORS_ORIGIN'] ?? 'http://localhost:3000', credentials: true, + methods: ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], }); await app.register(helmet as never, { contentSecurityPolicy: false }); diff --git a/apps/web/src/app/(dashboard)/chat/page.tsx b/apps/web/src/app/(dashboard)/chat/page.tsx index a04867d..68bea36 100644 --- a/apps/web/src/app/(dashboard)/chat/page.tsx +++ b/apps/web/src/app/(dashboard)/chat/page.tsx @@ -151,11 +151,15 @@ export default function ChatPage(): React.ReactElement { const handleDelete = useCallback( async (id: string) => { - await api(`/api/conversations/${id}`, { method: 'DELETE' }); - setConversations((prev) => prev.filter((c) => c.id !== id)); - if (activeId === id) { - setActiveId(null); - setMessages([]); + try { + await api(`/api/conversations/${id}`, { method: 'DELETE' }); + setConversations((prev) => prev.filter((c) => c.id !== id)); + if (activeId === id) { + setActiveId(null); + setMessages([]); + } + } catch (err) { + console.error('[ChatPage] Failed to delete conversation:', err); } }, [activeId],