From ca13eca7bdf329e283fb4d6ce8188da8651d86ed Mon Sep 17 00:00:00 2001 From: Zane <75694352+zanesq@users.noreply.github.com> Date: Thu, 17 Jul 2025 15:33:44 -0700 Subject: [PATCH] Fix llm errors not propagating to the ui and auto summarize not starting (#3490) --- ui/desktop/src/components/BaseChat.tsx | 77 +++++++++++++++++------- ui/desktop/src/hooks/useChatEngine.ts | 17 ++++++ ui/desktop/src/hooks/useMessageStream.ts | 50 ++++++++++++++- 3 files changed, 118 insertions(+), 26 deletions(-) diff --git a/ui/desktop/src/components/BaseChat.tsx b/ui/desktop/src/components/BaseChat.tsx index f26ab7c0..247d8bee 100644 --- a/ui/desktop/src/components/BaseChat.tsx +++ b/ui/desktop/src/components/BaseChat.tsx @@ -237,7 +237,6 @@ function BaseChatContent({ }); useEffect(() => { - // Log all messages when the component first mounts window.electron.logInfo( 'Initial messages when resuming session: ' + JSON.stringify(chat.messages, null, 2) ); @@ -414,28 +413,60 @@ function BaseChatContent({ )} - {error && ( -
-
- {error.message || 'Honk! Goose experienced an error while responding'} -
-
{ - // Find the last user message - const lastUserMessage = messages.reduceRight( - (found, m) => found || (m.role === 'user' ? m : null), - null as Message | null - ); - if (lastUserMessage) { - append(lastUserMessage); - } - }} - > - Retry Last Message -
-
- )} + {error && + !(error as Error & { isTokenLimitError?: boolean }).isTokenLimitError && ( + <> +
+
+ {error.message || 'Honk! Goose experienced an error while responding'} +
+ + {/* Expandable Error Details */} +
+ + Error details + +
+
+ Error Type: {error.name || 'Unknown'} +
+
+ Message: {error.message || 'No message'} +
+ {error.stack && ( +
+ Stack Trace: +
+                                    {error.stack}
+                                  
+
+ )} +
+
+ + {/* Regular retry button for non-token-limit errors */} +
{ + // Find the last user message + const lastUserMessage = messages.reduceRight( + (found, m) => found || (m.role === 'user' ? m : null), + null as Message | null + ); + if (lastUserMessage) { + append(lastUserMessage); + } + }} + > + Retry Last Message +
+
+ + )} + + {/* Token limit errors should be handled by ContextHandler, not shown here */} + {error && + (error as Error & { isTokenLimitError?: boolean }).isTokenLimitError && <>}
) : showPopularTopics ? ( diff --git a/ui/desktop/src/hooks/useChatEngine.ts b/ui/desktop/src/hooks/useChatEngine.ts index 857f99e6..c852b169 100644 --- a/ui/desktop/src/hooks/useChatEngine.ts +++ b/ui/desktop/src/hooks/useChatEngine.ts @@ -108,6 +108,23 @@ export const useChatEngine = ({ onMessageStreamFinish?.(); }, + onError: (error) => { + console.log( + 'CHAT ENGINE RECEIVED ERROR FROM MESSAGE STREAM:', + JSON.stringify( + { + errorMessage: error.message, + errorName: error.name, + isTokenLimitError: (error as Error & { isTokenLimitError?: boolean }).isTokenLimitError, + errorStack: error.stack, + timestamp: new Date().toISOString(), + chatId: chat.id, + }, + null, + 2 + ) + ); + }, }); // Wrap append to store messages in global history (if enabled) diff --git a/ui/desktop/src/hooks/useMessageStream.ts b/ui/desktop/src/hooks/useMessageStream.ts index 4277b16a..1f300f0c 100644 --- a/ui/desktop/src/hooks/useMessageStream.ts +++ b/ui/desktop/src/hooks/useMessageStream.ts @@ -323,8 +323,45 @@ export function useMessageStream({ break; } - case 'Error': - throw new Error(parsedEvent.error); + case 'Error': { + // Check if this is a token limit error (more specific detection) + const errorMessage = parsedEvent.error; + const isTokenLimitError = + errorMessage && + ((errorMessage.toLowerCase().includes('token') && + errorMessage.toLowerCase().includes('limit')) || + (errorMessage.toLowerCase().includes('context') && + errorMessage.toLowerCase().includes('length') && + errorMessage.toLowerCase().includes('exceeded'))); + + // If this is a token limit error, create a contextLengthExceeded message instead of throwing + if (isTokenLimitError) { + const contextMessage: Message = { + id: `context-${Date.now()}`, + role: 'assistant', + created: Math.floor(Date.now() / 1000), + content: [ + { + type: 'contextLengthExceeded', + msg: errorMessage, + }, + ], + display: true, + sendToLLM: false, + }; + + currentMessages = [...currentMessages, contextMessage]; + mutate(currentMessages, false); + + // Clear any existing error state since we handled this as a context message + setError(undefined); + break; // Don't throw error, just add the message + } + + // For non-token-limit errors, still throw the error + const error = new Error(parsedEvent.error); + throw error; + } case 'Finish': { // Call onFinish with the last message if available @@ -371,6 +408,11 @@ export function useMessageStream({ if (onError && e instanceof Error) { onError(e); } + // Don't re-throw here, let the error be handled by the outer catch + // Instead, set the error state directly + if (e instanceof Error) { + setError(e); + } } } } @@ -381,6 +423,8 @@ export function useMessageStream({ if (onError) { onError(e); } + // Re-throw the error so it gets caught by sendRequest and sets the error state + throw e; } } finally { reader.releaseLock(); @@ -388,7 +432,7 @@ export function useMessageStream({ return currentMessages; }, - [mutate, onFinish, onError, forceUpdate] + [mutate, onFinish, onError, forceUpdate, setError] ); // Send a request to the server