From fd90f86557f0c63ee5def4f9c8c67d640460f3cd Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 27 Aug 2026 15:17:21 +0000 Subject: [PATCH] Sanitize user-facing error messages and log to console Ensure all codebase error details and raw exceptions are hidden from user UI components, toasts, and streamable values while logging detailed errors to console.error for debugging. Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com> --- app/actions.tsx | 2 +- components/chat-share.tsx | 6 ++++-- components/clear-history.tsx | 3 ++- components/copilot-optimized.tsx | 14 ++++++++++---- components/copilot.tsx | 14 ++++++++++---- components/download-report-button.tsx | 2 +- components/message.tsx | 16 +++++++++++++++- components/settings/components/settings.tsx | 3 ++- .../settings/components/system-prompt-form.tsx | 6 ++++-- .../components/user-management-form.tsx | 5 +++-- components/sidebar/chat-history-client.tsx | 17 +++++------------ components/skyfi-section.tsx | 3 ++- lib/agents/tools/retrieve.tsx | 6 ++++-- 13 files changed, 63 insertions(+), 34 deletions(-) diff --git a/app/actions.tsx b/app/actions.tsx index 6f781fc5..0d020806 100644 --- a/app/actions.tsx +++ b/app/actions.tsx @@ -278,7 +278,7 @@ async function submit(formData?: FormData, skip?: boolean) { }; } catch (err: any) { console.error('Failed to parse files or initialize resolution search:', err); - const errorStream = createStreamableValue(`Failed to perform resolution search: ${err?.message || 'Invalid parameters.'}`); + const errorStream = createStreamableValue('Failed to perform resolution search. Please try again.'); errorStream.done(); isGenerating.done(false); uiStream.done(); diff --git a/components/chat-share.tsx b/components/chat-share.tsx index 18427739..33a53180 100644 --- a/components/chat-share.tsx +++ b/components/chat-share.tsx @@ -70,7 +70,8 @@ export function ChatShare({ chatId, className }: ChatShareProps) { setEmailInput('') fetchParticipants() } catch (err: any) { - toast.error(err.message || 'Error inviting collaborator') + console.error('Failed to add collaborator:', err) + toast.error('Unable to invite collaborator. Please check the details and try again.') } }) } @@ -93,7 +94,8 @@ export function ChatShare({ chatId, className }: ChatShareProps) { toast.success('Collaborator removed') fetchParticipants() } catch (err: any) { - toast.error(err.message || 'Error removing collaborator') + console.error('Failed to remove collaborator:', err) + toast.error('Unable to remove collaborator. Please try again.') } } diff --git a/components/clear-history.tsx b/components/clear-history.tsx index 73dab643..47672f66 100644 --- a/components/clear-history.tsx +++ b/components/clear-history.tsx @@ -48,7 +48,8 @@ export function ClearHistory({ empty }: ClearHistoryProps) { startTransition(async () => { const result = await clearChats() if (result?.error) { - toast.error(result.error) + console.error('Clear history error:', result.error) + toast.error('Unable to clear history. Please try again.') } else { toast.success('History cleared') } diff --git a/components/copilot-optimized.tsx b/components/copilot-optimized.tsx index 246a5b9b..b79d90d4 100644 --- a/components/copilot-optimized.tsx +++ b/components/copilot-optimized.tsx @@ -96,15 +96,21 @@ export const Copilot: React.FC = React.memo(({ inquiry }: CopilotP onFormSubmit(e as unknown as React.FormEvent, true) }, [onFormSubmit]) + useEffect(() => { + if (error) { + console.error('Copilot inquiry error:', error) + } + }, [error]) + // OPTIMIZATION: Memoize error card const errorCard = useMemo(() => { if (!error) return null; return ( - +
- -
- {`error: ${error}`} + +
+ An error occurred during inquiry generation. Please try again.
diff --git a/components/copilot.tsx b/components/copilot.tsx index 246a5b9b..b79d90d4 100644 --- a/components/copilot.tsx +++ b/components/copilot.tsx @@ -96,15 +96,21 @@ export const Copilot: React.FC = React.memo(({ inquiry }: CopilotP onFormSubmit(e as unknown as React.FormEvent, true) }, [onFormSubmit]) + useEffect(() => { + if (error) { + console.error('Copilot inquiry error:', error) + } + }, [error]) + // OPTIMIZATION: Memoize error card const errorCard = useMemo(() => { if (!error) return null; return ( - +
- -
- {`error: ${error}`} + +
+ An error occurred during inquiry generation. Please try again.
diff --git a/components/download-report-button.tsx b/components/download-report-button.tsx index a7a731f9..f07ed7f2 100644 --- a/components/download-report-button.tsx +++ b/components/download-report-button.tsx @@ -80,7 +80,7 @@ export const DownloadReportButton = () => { toast.success('Report generated successfully', { id: toastId }) } catch (error) { console.error('Failed to generate report:', error) - toast.error(`Report generation failed: ${error instanceof Error ? error.message : 'Unknown error'}`, { id: toastId }) + toast.error('Report generation failed. Please try again.', { id: toastId }) } finally { setIsGenerating(false) setShowTemplate(false) diff --git a/components/message.tsx b/components/message.tsx index 264aa1f6..adbb7002 100644 --- a/components/message.tsx +++ b/components/message.tsx @@ -8,11 +8,25 @@ import remarkMath from 'remark-math' import rehypeKatex from 'rehype-katex' import 'katex/dist/katex.min.css' +import { useEffect } from 'react' + export function BotMessage({ content }: { content: StreamableValue }) { const [data, error, pending] = useStreamableValue(content) + useEffect(() => { + if (error) { + console.error('BotMessage stream error:', error) + } + }, [error]) + // Currently, sometimes error occurs after finishing the stream. - if (error) return
Error
+ if (error) { + return ( +
+ An error occurred while generating the response. Please try again. +
+ ) + } //modify the content to render LaTeX equations const processedData = preprocessLaTeX(data || '') diff --git a/components/settings/components/settings.tsx b/components/settings/components/settings.tsx index 621b03f8..8cbd659a 100644 --- a/components/settings/components/settings.tsx +++ b/components/settings/components/settings.tsx @@ -150,10 +150,11 @@ export function Settings({ initialTab = "system-prompt" }: SettingsProps) { description: "Your settings have been saved successfully.", }) } catch (error: any) { + console.error("Failed to save settings:", error) // Error notification toast({ title: "Something went wrong", - description: error.message || "Your settings could not be saved. Please try again.", + description: "Your settings could not be saved. Please try again.", variant: "destructive", }) } finally { diff --git a/components/settings/components/system-prompt-form.tsx b/components/settings/components/system-prompt-form.tsx index 41022b80..304114d1 100644 --- a/components/settings/components/system-prompt-form.tsx +++ b/components/settings/components/system-prompt-form.tsx @@ -34,9 +34,10 @@ export function SystemPromptForm({ form }: SystemPromptFormProps) { const result = await startSystemPromptGeneration(domain) if (result.error) { + console.error("System prompt generation initiation error:", result.error) toast({ title: "Generation failed", - description: result.error, + description: "An error occurred starting prompt generation. Please try again.", variant: "destructive", }) setIsGenerating(false) @@ -69,12 +70,13 @@ export function SystemPromptForm({ form }: SystemPromptFormProps) { const job = await getSystemPromptGenerationJob(jobId) if (job.error || job.status === 'error') { + console.error("System prompt generation job error:", job.errorMessage || job.error) if (interval) clearInterval(interval) setJobId(null) setIsGenerating(false) toast({ title: "Generation error", - description: job.errorMessage || job.error || "An error occurred during generation.", + description: "An error occurred during prompt generation. Please try again.", variant: "destructive", }) } else if (job.status === 'complete') { diff --git a/components/settings/components/user-management-form.tsx b/components/settings/components/user-management-form.tsx index b9019838..b1709ca1 100644 --- a/components/settings/components/user-management-form.tsx +++ b/components/settings/components/user-management-form.tsx @@ -49,8 +49,9 @@ export function UserManagementForm({ form }: UserManagementFormProps) { const result = await addUser({ email: newUserEmail, role: newUserRole as UserRole }); if (result.error) { - toast({ title: 'Error adding user', description: result.error, variant: 'destructive' }); - form.setError("newUserEmail", { type: "manual", message: result.error }); + console.error("Add user server error:", result.error); + toast({ title: 'Error adding user', description: 'Failed to add user. Please check the details and try again.', variant: 'destructive' }); + form.setError("newUserEmail", { type: "manual", message: "Failed to add user." }); } else if (result.user) { toast({ title: 'User Added', description: `${result.user.email} was successfully added.` }); append({ diff --git a/components/sidebar/chat-history-client.tsx b/components/sidebar/chat-history-client.tsx index b43c4792..18cee2fe 100644 --- a/components/sidebar/chat-history-client.tsx +++ b/components/sidebar/chat-history-client.tsx @@ -63,13 +63,9 @@ export function ChatHistoryClient({}: ChatHistoryClientProps) { const data: { chats: DrizzleChat[], nextOffset: number | null } = await response.json(); setChats(data.chats); } catch (err) { - if (err instanceof Error) { - setError(err.message); - toast.error(`Error fetching chats: ${err.message}`); - } else { - setError('An unknown error occurred.'); - toast.error('Error fetching chats: An unknown error occurred.'); - } + console.error('Failed to fetch chats:', err); + setError('Failed to load chat history.'); + toast.error('Unable to fetch chat history. Please try again.'); } finally { setIsLoading(false); } @@ -97,11 +93,8 @@ export function ChatHistoryClient({}: ChatHistoryClientProps) { setIsAlertDialogOpen(false); router.refresh(); } catch (err) { - if (err instanceof Error) { - toast.error(err.message); - } else { - toast.error('An unknown error occurred while clearing history.'); - } + console.error('Failed to clear chat history:', err); + toast.error('Unable to clear history. Please try again.'); setIsAlertDialogOpen(false); } }); diff --git a/components/skyfi-section.tsx b/components/skyfi-section.tsx index 69b56ad4..ffbe4d32 100644 --- a/components/skyfi-section.tsx +++ b/components/skyfi-section.tsx @@ -36,6 +36,7 @@ export function SkyfiSection({ result }: SkyfiSectionProps) { // Handle stream error explicitly if (error) { + console.error('SkyFi tool execution error:', error) return (
@@ -43,7 +44,7 @@ export function SkyfiSection({ result }: SkyfiSectionProps) {
- {(error as any).message || String(error)} + An error occurred while communicating with SkyFi. Please try again later.
diff --git a/lib/agents/tools/retrieve.tsx b/lib/agents/tools/retrieve.tsx index baaea04a..7d75dd7d 100644 --- a/lib/agents/tools/retrieve.tsx +++ b/lib/agents/tools/retrieve.tsx @@ -42,10 +42,12 @@ export const retrieveTool = ({ uiStream, fullResponse }: ToolProps) => ({ hasError = true console.error('Retrieve API error:', error) - fullResponse += `\n${error} "${url}".` + fullResponse += `\nAn error occurred while retrieving content from "${url}".` uiStream.update( - {`${error} "${url}".`} + + {`An error occurred while retrieving content from "${url}".`} + ) return results }