From 84a309d669f69ca7c9a43e997fc694d192459f31 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Wed, 21 Jan 2026 14:07:23 +0100 Subject: [PATCH] fix: ttd 429 error handling (#10680) --- .../components/TTDDialog/TTDDialogOutput.tsx | 4 +- .../TTDDialog/hooks/useTextGeneration.ts | 128 +++++++----------- packages/excalidraw/locales/en.json | 6 +- 3 files changed, 57 insertions(+), 81 deletions(-) diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogOutput.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogOutput.tsx index f19d459633..443ccc4d3e 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogOutput.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogOutput.tsx @@ -37,7 +37,9 @@ export const TTDDialogOutput = ({ {t("ttd.error")}
- {hideErrorDetails ? t("ttd.errorMermaidSyntax") : error.message} + {hideErrorDetails + ? t("chat.errors.mermaidParseError") + : error.message}
diff --git a/packages/excalidraw/components/TTDDialog/hooks/useTextGeneration.ts b/packages/excalidraw/components/TTDDialog/hooks/useTextGeneration.ts index 47c91584e8..e31847ae0c 100644 --- a/packages/excalidraw/components/TTDDialog/hooks/useTextGeneration.ts +++ b/packages/excalidraw/components/TTDDialog/hooks/useTextGeneration.ts @@ -63,31 +63,6 @@ export const useTextGeneration = ({ return true; }; - const getReadableErrorMsg = (msg: string) => { - try { - const content = JSON.parse(msg); - - const innerMessages = JSON.parse(content.message); - - return innerMessages - .map((oneMsg: { message: string }) => oneMsg.message) - .join("\n"); - } catch (err) { - return msg; - } - }; - - const handleError = (error: Error, errorType: "parse" | "network") => { - if (errorType === "parse") { - trackEvent("ai", "mermaid parse failed", "ttd"); - } - - const msg = getReadableErrorMsg(error.message); - - setAssistantError(msg, errorType); - setError(error); - }; - const onGenerate: TTTDDialog.OnGenerate = async ({ prompt, isRepairFlow = false, @@ -165,6 +140,34 @@ export const useTextGeneration = ({ setRateLimits({ rateLimit, rateLimitRemaining }); } + if (error?.status === 429 || rateLimitRemaining === 0) { + setChatHistory((chatHistory) => { + if (error?.status === 429) { + chatHistory = removeLastAssistantMessage(chatHistory); + } + + chatHistory = { + ...chatHistory, + messages: chatHistory.messages.filter( + (msg) => + msg.type !== "warning" || + msg.warningType === "rateLimitExceeded" || + msg.warningType === "messageLimitExceeded", + ), + }; + const messages = addMessages(chatHistory, [ + { + type: "warning", + warningType: + rateLimitRemaining === 0 + ? "messageLimitExceeded" + : "rateLimitExceeded", + }, + ]); + return messages; + }); + } + if (error) { const isAborted = error.name === "AbortError" || @@ -176,63 +179,34 @@ export const useTextGeneration = ({ return; } - if (error.status === 429) { - setChatHistory((prev) => { - const chatHistory = removeLastAssistantMessage(prev); - - return { - ...chatHistory, - messages: chatHistory.messages.filter( - (msg) => - msg.type !== "warning" || - msg.warningType === "rateLimitExceeded" || - msg.warningType === "messageLimitExceeded", - ), - }; - }); - - setChatHistory((chatHistory) => { - return addMessages(chatHistory, [ - { - type: "warning", - warningType: - rateLimitRemaining === 0 - ? "messageLimitExceeded" - : "rateLimitExceeded", - }, - ]); - }); - - return; - } else if (rateLimitRemaining === 0) { - setChatHistory((chatHistory) => { - chatHistory = { - ...chatHistory, - messages: chatHistory.messages.filter( - (msg) => - msg.type !== "warning" || - msg.warningType === "rateLimitExceeded" || - msg.warningType === "messageLimitExceeded", - ), - }; - return addMessages(chatHistory, [ - { - type: "warning", - warningType: "messageLimitExceeded", - }, - ]); - }); + const _error = new Error( + error.message || t("chat.errors.requestFailed"), + ); + if (error.status !== 429) { + setAssistantError(_error.message, "network"); } + setError(_error); - handleError(error as Error, "network"); return; } - await parseMermaidToExcalidraw(generatedResponse ?? ""); - - trackEvent("ai", "mermaid parse success", "ttd"); - } catch (error: unknown) { - handleError(error as Error, "parse"); + try { + await parseMermaidToExcalidraw(generatedResponse ?? ""); + trackEvent("ai", "mermaid parse success", "ttd"); + } catch (error: any) { + trackEvent("ai", "mermaid parse failed", "ttd"); + const _error = new Error( + error.message || t("chat.errors.mermaidParseError"), + ); + setAssistantError(_error.message, "parse"); + setError(_error); + } + } catch (error: any) { + const _error = new Error( + error.message || t("chat.errors.generationFailed"), + ); + setAssistantError(_error.message, "other"); + setError(_error); } finally { streamingAbortControllerRef.current = null; } diff --git a/packages/excalidraw/locales/en.json b/packages/excalidraw/locales/en.json index dd69162c3f..b66485c73d 100644 --- a/packages/excalidraw/locales/en.json +++ b/packages/excalidraw/locales/en.json @@ -617,8 +617,7 @@ "inputPlaceholder": "Write Mermaid diagram defintion here..." }, "ttd": { - "error": "Error!", - "errorMermaidSyntax": "Mermaid syntax error" + "error": "Error!" }, "chat": { "inputPlaceholder": "Start typing your diagram idea here... ({{shortcut}} for new line)", @@ -653,7 +652,8 @@ "fixInMermaid": "Edit Mermaid manually →", "aiRepair": "Regenerate (auto-fix) →", "requestAborted": "Request aborted", - "requestFailed": "Request failed" + "requestFailed": "Request failed", + "mermaidParseError": "Mermaid syntax error" }, "rateLimit": { "messageLimit": "You've hit your AI limit on the free plan. Try out Excalidraw+ for more or come back tomorrow.",