Use errorMessage (#6749)

Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
Douwe Osinga
2026-01-28 10:29:10 -05:00
committed by GitHub
parent 7f98f1f5f9
commit 710e7f35ed
29 changed files with 109 additions and 100 deletions
+2 -2
View File
@@ -419,7 +419,7 @@ export function AppInner() {
} catch (error) {
console.error('Error sending reactReady:', error);
setFatalError(
`React ready notification failed: ${error instanceof Error ? error.message : 'Unknown error'}`
`React ready notification failed: ${errorMessage(error, 'Unknown error')}`
);
}
}, []);
@@ -445,7 +445,7 @@ export function AppInner() {
const shareToken = link.replace('goose://sessions/', '');
const options = {
sessionDetails: null,
error: error instanceof Error ? error.message : 'Unknown error',
error: errorMessage(error, 'Unknown error'),
shareToken,
};
navigate('/shared-session', { state: options });
@@ -15,6 +15,7 @@ import type { ExtensionConfig } from '../api/types.gen';
import { View, ViewOptions } from '../utils/navigationUtils';
import { useConfig } from './ConfigContext';
import { toastService } from '../toasts';
import { errorMessage } from '../utils/conversionUtils';
type ModalType = 'blocked' | 'untrusted' | 'trusted';
@@ -208,7 +209,7 @@ export function ExtensionInstallModal({ addExtension, setView }: ExtensionInstal
console.error('Error processing extension request:', error);
setModalState((prev) => ({
...prev,
error: error instanceof Error ? error.message : 'Unknown error',
error: errorMessage(error, 'Unknown error'),
}));
} finally {
processingLinkRef.current = null;
@@ -248,16 +249,11 @@ export function ExtensionInstallModal({ addExtension, setView }: ExtensionInstal
} else {
throw new Error('addExtension function not provided to component');
}
// Only dismiss modal after successful installation
dismissModal();
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Installation failed';
console.error('Extension installation failed:', error);
setModalState((prev) => ({
...prev,
error: errorMessage,
error: errorMessage(error, 'Installation failed'),
isPending: false,
}));
}
@@ -12,6 +12,7 @@ import { useState, useEffect } from 'react';
import { toast } from 'react-toastify';
import { EmbeddedResource } from '../api';
import { useTheme } from '../contexts/ThemeContext';
import { errorMessage } from '../utils/conversionUtils';
interface MCPUIResourceRendererProps {
content: EmbeddedResource & { type: 'resource' };
@@ -154,7 +155,7 @@ export default function MCPUIResourceRenderer({
error: {
code: UIActionErrorCode.PROMPT_FAILED,
message: 'Failed to send prompt to chat',
details: error instanceof Error ? error.message : error,
details: errorMessage(error),
},
};
}
@@ -218,7 +219,7 @@ export default function MCPUIResourceRenderer({
error: {
code: UIActionErrorCode.NAVIGATION_FAILED,
message: `Unexpected error opening URL: ${url}`,
details: error instanceof Error ? error.message : error,
details: errorMessage(error),
},
};
}
@@ -21,6 +21,7 @@ import {
import { cn } from '../../utils';
import { DEFAULT_IFRAME_HEIGHT } from './utils';
import { readResource, callTool } from '../../api';
import { errorMessage } from '../../utils/conversionUtils';
interface McpAppRendererProps {
resourceUri: string;
@@ -92,7 +93,7 @@ export default function McpAppRenderer({
}
} catch (err) {
if (!cachedHtml) {
setError(err instanceof Error ? err.message : 'Failed to load resource');
setError(errorMessage(err, 'Failed to load resource'));
} else {
console.warn('Failed to fetch fresh resource, using cached version:', err);
}
@@ -3,15 +3,13 @@ import { toastError, toastSuccess } from '../toasts';
import Model, { getProviderMetadata } from './settings/models/modelInterface';
import { ProviderMetadata, setConfigProvider, updateAgentProvider } from '../api';
import { useConfig } from './ConfigContext';
import { errorMessage } from '../utils/conversionUtils';
import {
getModelDisplayName,
getProviderDisplayName,
} from './settings/models/predefinedModelsUtils';
// titles
export const UNKNOWN_PROVIDER_TITLE = 'Provider name lookup';
// errors
export const UNKNOWN_PROVIDER_MSG = 'Unknown provider in config -- please inspect your config.yaml';
// success
@@ -80,7 +78,7 @@ export const ModelAndProviderProvider: React.FC<ModelAndProviderProviderProps> =
toastError({
title: `${providerName}/${modelName} failed`,
msg: `${error}`,
traceback: error instanceof Error ? error.message : String(error),
traceback: errorMessage(error),
});
}
}, []);
+2 -2
View File
@@ -9,9 +9,9 @@ import {
getPreferredModel,
type PullProgress,
} from '../utils/ollamaDetection';
//import { initializeSystem } from '../utils/providerUtils';
import { toastService } from '../toasts';
import { Ollama } from './icons';
import { errorMessage } from '../utils/conversionUtils';
interface OllamaSetupProps {
onSuccess: () => void;
@@ -120,7 +120,7 @@ export function OllamaSetup({ onSuccess, onCancel }: OllamaSetupProps) {
console.error('Failed to connect to Ollama:', error);
toastService.error({
title: 'Connection Failed',
msg: `Failed to connect to Ollama: ${error instanceof Error ? error.message : String(error)}`,
msg: `Failed to connect to Ollama: ${errorMessage(error)}`,
traceback: error instanceof Error ? error.stack || '' : '',
});
setIsConnecting(false);
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import { IoIosCloseCircle, IoIosWarning, IoIosInformationCircle } from 'react-icons/io';
import { FaPencilAlt, FaSave } from 'react-icons/fa';
import { cn } from '../../utils';
import { errorMessage } from '../../utils/conversionUtils';
import { Alert, AlertType } from './types';
import { upsertConfig } from '../../api';
import { useConfig } from '../ConfigContext';
@@ -90,7 +91,7 @@ export const AlertBox = ({ alert, className }: AlertBoxProps) => {
} catch (error) {
console.error('Error saving threshold:', error);
window.alert(
`Failed to save threshold: ${error instanceof Error ? error.message : 'Unknown error'}`
`Failed to save threshold: ${errorMessage(error, 'Unknown error')}`
);
} finally {
setIsSaving(false);
+5 -4
View File
@@ -5,6 +5,7 @@ import { Download, Play, Upload } from 'lucide-react';
import { exportApp, GooseApp, importApp, listApps } from '../../api';
import { useChatContext } from '../../contexts/ChatContext';
import { formatAppName } from '../../utils/conversionUtils';
import { errorMessage } from '../../utils/conversionUtils';
const GridLayout = ({ children }: { children: React.ReactNode }) => {
return (
@@ -63,7 +64,7 @@ export default function AppsView() {
console.warn('Failed to refresh apps:', err);
// Don't set error if we already have cached apps
if (apps.length === 0) {
setError(err instanceof Error ? err.message : 'Failed to load apps');
setError(errorMessage(err, 'Failed to load apps'));
}
}
};
@@ -115,7 +116,7 @@ export default function AppsView() {
} catch (err) {
// Only set error if we don't have apps to show
if (apps.length === 0) {
setError(err instanceof Error ? err.message : 'Failed to load apps');
setError(errorMessage(err, 'Failed to load apps'));
}
} finally {
setLoading(false);
@@ -151,7 +152,7 @@ export default function AppsView() {
}
} catch (err) {
console.error('Failed to export app:', err);
setError(err instanceof Error ? err.message : 'Failed to export app');
setError(errorMessage(err, 'Failed to export app'));
}
};
@@ -179,7 +180,7 @@ export default function AppsView() {
setError(null);
} catch (err) {
console.error('Failed to import app:', err);
setError(err instanceof Error ? err.message : 'Failed to import app');
setError(errorMessage(err, 'Failed to import app'));
}
event.target.value = '';
};
@@ -3,6 +3,7 @@ import { useSearchParams } from 'react-router-dom';
import McpAppRenderer from '../McpApps/McpAppRenderer';
import { startAgent, resumeAgent, listApps, stopAgent } from '../../api';
import { formatAppName } from '../../utils/conversionUtils';
import { errorMessage } from '../../utils/conversionUtils';
export default function StandaloneAppView() {
const [searchParams] = useSearchParams();
@@ -78,7 +79,7 @@ export default function StandaloneAppView() {
} catch (err) {
console.error('Failed to initialize session:', err);
if (!cachedHtml) {
setError(err instanceof Error ? err.message : 'Failed to initialize session');
setError(errorMessage(err, 'Failed to initialize session'));
setLoading(false);
}
}
@@ -11,6 +11,7 @@ import { RecipeFormFields } from './shared/RecipeFormFields';
import { RecipeFormData } from './shared/recipeFormSchema';
import { toastSuccess, toastError } from '../../toasts';
import { saveRecipe } from '../../recipe/recipe_management';
import { errorMessage } from '../../utils/conversionUtils';
interface CreateEditRecipeModalProps {
isOpen: boolean;
@@ -272,8 +273,8 @@ export default function CreateEditRecipeModal({
toastError({
title: 'Save Failed',
msg: `Failed to save recipe: ${error instanceof Error ? error.message : 'Unknown error'}`,
traceback: error instanceof Error ? error.message : String(error),
msg: `Failed to save recipe: ${errorMessage(error, 'Unknown error')}`,
traceback: errorMessage(error),
});
} finally {
setIsSaving(false);
@@ -317,8 +318,8 @@ export default function CreateEditRecipeModal({
toastError({
title: 'Save and Run Failed',
msg: `Failed to save and run recipe: ${error instanceof Error ? error.message : 'Unknown error'}`,
traceback: error instanceof Error ? error.message : String(error),
msg: `Failed to save and run recipe: ${errorMessage(error, 'Unknown error')}`,
traceback: errorMessage(error),
});
} finally {
setIsSaving(false);
@@ -10,6 +10,7 @@ import { createRecipe } from '../../api/sdk.gen';
import { RecipeParameter } from './shared/recipeFormSchema';
import { toastError } from '../../toasts';
import { saveRecipe } from '../../recipe/recipe_management';
import { errorMessage } from '../../utils/conversionUtils';
interface CreateRecipeFromSessionModalProps {
isOpen: boolean;
@@ -202,10 +203,10 @@ export default function CreateRecipeFromSessionModal({
console.error('Failed to create recipe:', error);
toastError({
title: 'Failed to create recipe',
msg:
error instanceof Error
? error.message
: 'An unexpected error occurred while creating the recipe. Please try again.',
msg: errorMessage(
error,
'An unexpected error occurred while creating the recipe. Please try again.'
),
});
} finally {
setIsCreating(false);
@@ -10,6 +10,7 @@ import { useEscapeKey } from '../../hooks/useEscapeKey';
import { getRecipeJsonSchema } from '../../recipe/validation';
import { saveRecipe } from '../../recipe/recipe_management';
import { parseRecipe } from '../../api';
import { errorMessage } from '../../utils/conversionUtils';
interface ImportRecipeFormProps {
isOpen: boolean;
@@ -138,8 +139,8 @@ export default function ImportRecipeForm({ isOpen, onClose, onSuccess }: ImportR
toastError({
title: 'Import Failed',
msg: `Failed to import recipe: ${error instanceof Error ? error.message : 'Unknown error'}`,
traceback: error instanceof Error ? error.message : String(error),
msg: `Failed to import recipe: ${errorMessage(error, 'Unknown error')}`,
traceback: errorMessage(error),
});
} finally {
setImporting(false);
@@ -167,7 +168,7 @@ export default function ImportRecipeForm({ isOpen, onClose, onSuccess }: ImportR
} catch (error) {
toastError({
title: 'Invalid Deeplink',
msg: `The deeplink format is invalid: ${error instanceof Error ? error.message : 'Unknown error'}`,
msg: `The deeplink format is invalid: ${errorMessage(error, 'Unknown error')}`,
});
}
}
@@ -183,7 +184,7 @@ export default function ImportRecipeForm({ isOpen, onClose, onSuccess }: ImportR
} catch (error) {
toastError({
title: 'Invalid Recipe File',
msg: error instanceof Error ? error.message : 'Unknown error',
msg: errorMessage(error, 'Unknown error'),
});
}
}
@@ -57,6 +57,7 @@ import {
DropdownMenuSeparator,
} from '../ui/dropdown-menu';
import { getSearchShortcutText } from '../../utils/keyboardShortcuts';
import { errorMessage } from '../../utils/conversionUtils';
export default function RecipesView() {
const setView = useNavigation();
@@ -130,7 +131,7 @@ export default function RecipesView() {
const recipeManifestResponses = await listSavedRecipes();
setSavedRecipes(recipeManifestResponses);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load recipes');
setError(errorMessage(err, 'Failed to load recipes'));
console.error('Failed to load saved recipes:', err);
} finally {
setLoading(false);
@@ -154,7 +155,7 @@ export default function RecipesView() {
});
} catch (error) {
console.error('Failed to load recipe:', error);
const errorMsg = error instanceof Error ? error.message : 'Failed to load recipe';
const errorMsg = errorMessage(error, 'Failed to load recipe');
trackRecipeStarted(false, getErrorType(error), false);
setError(errorMsg);
}
@@ -201,7 +202,7 @@ export default function RecipesView() {
});
} catch (err) {
console.error('Failed to delete recipe:', err);
const errorMsg = err instanceof Error ? err.message : 'Failed to delete recipe';
const errorMsg = errorMessage(err, 'Failed to delete recipe');
trackRecipeDeleted(false, getErrorType(err));
setError(errorMsg);
}
@@ -341,7 +342,7 @@ export default function RecipesView() {
await loadSavedRecipes();
} catch (error) {
console.error('Failed to save schedule:', error);
const errorMsg = error instanceof Error ? error.message : 'Failed to save schedule';
const errorMsg = errorMessage(error, 'Failed to save schedule');
trackRecipeScheduled(false, action, getErrorType(error));
setError(errorMsg);
}
@@ -369,7 +370,7 @@ export default function RecipesView() {
await loadSavedRecipes();
} catch (error) {
console.error('Failed to remove schedule:', error);
const errorMsg = error instanceof Error ? error.message : 'Failed to remove schedule';
const errorMsg = errorMessage(error, 'Failed to remove schedule');
trackRecipeScheduled(false, 'remove', getErrorType(error));
setError(errorMsg);
}
@@ -409,7 +410,7 @@ export default function RecipesView() {
await loadSavedRecipes();
} catch (error) {
console.error('Failed to save slash command:', error);
const errorMsg = error instanceof Error ? error.message : 'Failed to save slash command';
const errorMsg = errorMessage(error, 'Failed to save slash command');
trackRecipeSlashCommandSet(false, action, getErrorType(error));
setError(errorMsg);
}
@@ -437,7 +438,7 @@ export default function RecipesView() {
await loadSavedRecipes();
} catch (error) {
console.error('Failed to remove slash command:', error);
const errorMsg = error instanceof Error ? error.message : 'Failed to remove slash command';
const errorMsg = errorMessage(error, 'Failed to remove slash command');
trackRecipeSlashCommandSet(false, 'remove', getErrorType(error));
setError(errorMsg);
}
@@ -22,6 +22,7 @@ import cronstrue from 'cronstrue';
import { formatToLocalDateWithTimezone } from '../../utils/date';
import { getSession, Session } from '../../api';
import { trackScheduleRunNow, getErrorType } from '../../utils/analytics';
import { errorMessage } from '../../utils/conversionUtils';
interface ScheduleSessionMeta {
id: string;
@@ -67,7 +68,7 @@ const ScheduleDetailView: React.FC<ScheduleDetailViewProps> = ({ scheduleId, onN
const data = await getScheduleSessions(sId, 20);
setSessions(data);
} catch (err) {
setSessionsError(err instanceof Error ? err.message : 'Failed to fetch sessions');
setSessionsError(errorMessage(err, 'Failed to fetch sessions'));
} finally {
setIsLoadingSessions(false);
}
@@ -85,7 +86,7 @@ const ScheduleDetailView: React.FC<ScheduleDetailViewProps> = ({ scheduleId, onN
setScheduleError('Schedule not found');
}
} catch (err) {
setScheduleError(err instanceof Error ? err.message : 'Failed to fetch schedule');
setScheduleError(errorMessage(err, 'Failed to fetch schedule'));
} finally {
setIsLoadingSchedule(false);
}
@@ -112,7 +113,7 @@ const ScheduleDetailView: React.FC<ScheduleDetailViewProps> = ({ scheduleId, onN
await fetchSessions(scheduleId);
await fetchSchedule(scheduleId);
} catch (err) {
const errorMsg = err instanceof Error ? err.message : 'Failed to trigger schedule';
const errorMsg = errorMessage(err, 'Failed to trigger schedule');
trackScheduleRunNow(false, getErrorType(err));
toastError({
title: 'Run Schedule Error',
@@ -136,7 +137,7 @@ const ScheduleDetailView: React.FC<ScheduleDetailViewProps> = ({ scheduleId, onN
}
await fetchSchedule(scheduleId);
} catch (err) {
const errorMsg = err instanceof Error ? err.message : 'Operation failed';
const errorMsg = errorMessage(err, 'Operation failed');
toastError({
title: 'Pause/Unpause Error',
msg: errorMsg,
@@ -154,7 +155,7 @@ const ScheduleDetailView: React.FC<ScheduleDetailViewProps> = ({ scheduleId, onN
toastSuccess({ title: 'Job Killed', msg: result.message });
await fetchSchedule(scheduleId);
} catch (err) {
const errorMsg = err instanceof Error ? err.message : 'Failed to kill job';
const errorMsg = errorMessage(err, 'Failed to kill job');
toastError({
title: 'Kill Job Error',
msg: errorMsg,
@@ -181,7 +182,7 @@ const ScheduleDetailView: React.FC<ScheduleDetailViewProps> = ({ scheduleId, onN
toastSuccess({ title: 'Job Inspection', msg: 'No detailed information available' });
}
} catch (err) {
const errorMsg = err instanceof Error ? err.message : 'Failed to inspect job';
const errorMsg = errorMessage(err, 'Failed to inspect job');
toastError({
title: 'Inspect Job Error',
msg: errorMsg,
@@ -200,7 +201,7 @@ const ScheduleDetailView: React.FC<ScheduleDetailViewProps> = ({ scheduleId, onN
await fetchSchedule(scheduleId);
setIsModalOpen(false);
} catch (err) {
const errorMsg = err instanceof Error ? err.message : 'Failed to update schedule';
const errorMsg = errorMessage(err, 'Failed to update schedule');
toastError({
title: 'Update Schedule Error',
msg: errorMsg,
@@ -220,7 +221,7 @@ const ScheduleDetailView: React.FC<ScheduleDetailViewProps> = ({ scheduleId, onN
});
setSelectedSession(response.data);
} catch (err) {
const msg = err instanceof Error ? err.message : 'Failed to load session';
const msg = errorMessage(err, 'Failed to load session');
setSessionError(msg);
toastError({ title: 'Failed to load session', msg });
} finally {
@@ -21,6 +21,7 @@ import ScheduleDetailView from './ScheduleDetailView';
import { toastError, toastSuccess } from '../../toasts';
import cronstrue from 'cronstrue';
import { formatToLocalDateWithTimezone } from '../../utils/date';
import { errorMessage } from '../../utils/conversionUtils';
import { MainPanelLayout } from '../Layout/MainPanelLayout';
import { ViewOptions } from '../../utils/navigationUtils';
import { trackScheduleCreated, trackScheduleDeleted, getErrorType } from '../../utils/analytics';
@@ -206,9 +207,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
} catch (error) {
console.error('Failed to fetch schedules:', error);
setApiError(
error instanceof Error
? error.message
: 'An unknown error occurred while fetching schedules.'
errorMessage(error, 'An unknown error occurred while fetching schedules.')
);
} finally {
setIsLoading(false);
@@ -270,7 +269,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
setEditingSchedule(null);
} catch (error) {
console.error('Failed to save schedule:', error);
const errorMsg = error instanceof Error ? error.message : 'Unknown error saving schedule.';
const errorMsg = errorMessage(error, 'Unknown error saving schedule.');
setSubmitApiError(errorMsg);
if (!editingSchedule) {
@@ -295,7 +294,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
await fetchSchedules();
} catch (error) {
console.error(`Failed to delete schedule "${id}":`, error);
const errorMsg = error instanceof Error ? error.message : `Unknown error deleting "${id}".`;
const errorMsg = errorMessage(error, `Unknown error deleting "${id}".`);
setApiError(errorMsg);
trackScheduleDeleted(false, getErrorType(error));
} finally {
@@ -320,7 +319,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
await fetchSchedules();
} catch (error) {
console.error(`Failed to pause schedule "${id}":`, error);
const errorMsg = error instanceof Error ? error.message : `Unknown error pausing "${id}".`;
const errorMsg = errorMessage(error, `Unknown error pausing "${id}".`);
setApiError(errorMsg);
toastError({
title: 'Pause Schedule Error',
@@ -348,7 +347,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
await fetchSchedules();
} catch (error) {
console.error(`Failed to unpause schedule "${id}":`, error);
const errorMsg = error instanceof Error ? error.message : `Unknown error unpausing "${id}".`;
const errorMsg = errorMessage(error, `Unknown error unpausing "${id}".`);
setApiError(errorMsg);
toastError({
title: 'Unpause Schedule Error',
@@ -377,7 +376,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
} catch (error) {
console.error(`Failed to kill running job "${id}":`, error);
const errorMsg =
error instanceof Error ? error.message : `Unknown error killing job "${id}".`;
errorMessage(error, `Unknown error killing job "${id}".`);
setApiError(errorMsg);
toastError({
title: 'Kill Job Error',
@@ -415,7 +414,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
} catch (error) {
console.error(`Failed to inspect running job "${id}":`, error);
const errorMsg =
error instanceof Error ? error.message : `Unknown error inspecting job "${id}".`;
errorMessage(error, `Unknown error inspecting job "${id}".`);
setApiError(errorMsg);
toastError({
title: 'Inspect Job Error',
@@ -18,6 +18,7 @@ import { MainPanelLayout } from '../Layout/MainPanelLayout';
import { ScrollArea } from '../ui/scroll-area';
import { formatMessageTimestamp } from '../../utils/timeUtils';
import { createSharedSession } from '../../sharedSessions';
import { errorMessage } from '../../utils/conversionUtils';
import {
Dialog,
DialogContent,
@@ -189,7 +190,7 @@ const SessionHistoryView: React.FC<SessionHistoryViewProps> = ({
} catch (error) {
console.error('Error sharing session:', error);
toast.error(
`Failed to share session: ${error instanceof Error ? error.message : 'Unknown error'}`
`Failed to share session: ${errorMessage(error, 'Unknown error')}`
);
} finally {
setIsSharing(false);
@@ -213,7 +214,7 @@ const SessionHistoryView: React.FC<SessionHistoryViewProps> = ({
try {
resumeSession(session, setView);
} catch (error) {
toast.error(`Could not launch session: ${error instanceof Error ? error.message : error}`);
toast.error(`Could not launch session: ${errorMessage(error)}`);
}
};
@@ -22,6 +22,7 @@ import { SearchView } from '../conversation/SearchView';
import { SearchHighlighter } from '../../utils/searchHighlighter';
import { MainPanelLayout } from '../Layout/MainPanelLayout';
import { groupSessionsByDate, type DateGroup } from '../../utils/dateUtils';
import { errorMessage } from '../../utils/conversionUtils';
import { Skeleton } from '../ui/skeleton';
import { toast } from 'react-toastify';
import { ConfirmationModal } from '../ui/ConfirmationModal';
@@ -99,9 +100,9 @@ const EditSessionModal = React.memo<EditSessionModalProps>(
toast.success('Session description updated successfully');
}, 300);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
console.error('Failed to update session description:', errorMessage);
toast.error(`Failed to update session description: ${errorMessage}`);
const errMsg = errorMessage(error, 'Unknown error occurred');
console.error('Failed to update session description:', errMsg);
toast.error(`Failed to update session description: ${errMsg}`);
setDescription(session.name);
} finally {
setIsUpdating(false);
@@ -450,8 +451,7 @@ const SessionListView: React.FC<SessionListViewProps> = React.memo(
await loadSessions();
} catch (error) {
console.error('Error duplicating session:', error);
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
toast.error(`Failed to duplicate session: ${errorMessage}`);
toast.error(`Failed to duplicate session: ${errorMessage(error, 'Unknown error')}`);
}
},
[loadSessions]
@@ -476,8 +476,7 @@ const SessionListView: React.FC<SessionListViewProps> = React.memo(
);
} catch (error) {
console.error('Error deleting session:', error);
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
toast.error(`Failed to delete session "${sessionName}": ${errorMessage}`);
toast.error(`Failed to delete session "${sessionName}": ${errorMessage(error, 'Unknown error')}`);
}
await loadSessions();
}, [sessionToDelete, loadSessions]);
@@ -1,4 +1,5 @@
import { useEffect, useState } from 'react';
import { errorMessage } from '../../utils/conversionUtils';
import { Card, CardContent, CardDescription } from '../ui/card';
import { Greeting } from '../common/Greeting';
import { useNavigate } from 'react-router-dom';
@@ -34,7 +35,7 @@ export function SessionInsights() {
setError(null);
} catch (error) {
console.error('Failed to load insights:', error);
setError(error instanceof Error ? error.message : 'Failed to load insights');
setError(errorMessage(error, 'Failed to load insights'));
setInsights({
totalSessions: 0,
totalTokens: 0,
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import { Button } from '../../ui/button';
import { Loader2, Download, CheckCircle, AlertCircle } from 'lucide-react';
import { errorMessage } from '../../../utils/conversionUtils';
type UpdateStatus =
| 'idle'
@@ -154,7 +155,7 @@ export default function UpdateSection() {
console.error('Error checking for updates:', error);
setUpdateInfo((prev) => ({
...prev,
error: error instanceof Error ? error.message : 'Failed to check for updates',
error: errorMessage(error, 'Failed to check for updates'),
}));
setUpdateStatus('error');
setTimeout(() => setUpdateStatus('idle'), 5000);
@@ -17,6 +17,7 @@ import {
DialogTitle,
DialogTrigger,
} from '../../ui/dialog';
import { errorMessage } from '../../../utils/conversionUtils';
export default function ConfigSettings() {
const { config, upsert } = useConfig();
@@ -84,7 +85,7 @@ export default function ConfigSettings() {
toastError({
title: 'Save Failed',
msg: `Failed to save "${getUiNames(key)}"`,
traceback: error instanceof Error ? error.message : String(error),
traceback: errorMessage(error),
});
} finally {
setSaving(null);
@@ -1,4 +1,5 @@
import { ProviderDetails, getProviderModels } from '../../../api';
import { errorMessage as getErrorMessage } from '../../../utils/conversionUtils';
export default interface Model {
id?: number; // Make `id` optional to allow user-defined models
@@ -60,7 +61,8 @@ export async function fetchModelsForProviders(
const models = response.data || [];
return { provider: p, models, error: null };
} catch (e: unknown) {
const errorMessage = `Failed to fetch models for ${p.name}${e instanceof Error ? `: ${e.message}` : ''}`;
const errMsg = getErrorMessage(e);
const errorMessage = `Failed to fetch models for ${p.name}${errMsg ? `: ${errMsg}` : ''}`;
return {
provider: p,
models: null,
+2 -2
View File
@@ -1,5 +1,5 @@
import { useCallback, useState, useRef, useEffect } from 'react';
import { compressImageDataUrl } from '../utils/conversionUtils';
import { compressImageDataUrl, errorMessage } from '../utils/conversionUtils';
export interface DroppedFile {
id: string;
@@ -66,7 +66,7 @@ export const useFileDrop = () => {
type: file.type,
isImage: false,
isLoading: false,
error: `Failed to get file path: ${error instanceof Error ? error.message : 'Unknown error'}`,
error: `Failed to get file path: ${errorMessage(error, 'Unknown error')}`,
};
}
+2 -3
View File
@@ -3,7 +3,7 @@ import { useConfig } from '../components/ConfigContext';
import { getApiUrl } from '../config';
import { useDictationSettings } from './useDictationSettings';
import { DICTATION_PROVIDER_OPENAI, DICTATION_PROVIDER_ELEVENLABS } from './dictationConstants';
import { safeJsonParse } from '../utils/conversionUtils';
import { safeJsonParse, errorMessage } from '../utils/conversionUtils';
interface UseWhisperOptions {
onTranscription?: (text: string) => void;
@@ -353,8 +353,7 @@ export const useWhisper = ({ onTranscription, onError, onSizeWarning }: UseWhisp
setIsRecording(true);
} catch (startError) {
console.error('Error calling mediaRecorder.start():', startError);
const errorMessage = startError instanceof Error ? startError.message : String(startError);
throw new Error(`Failed to start recording: ${errorMessage}`);
throw new Error(`Failed to start recording: ${errorMessage(startError)}`);
}
} catch (error) {
console.error('Error starting recording:', error);
+2 -3
View File
@@ -28,7 +28,7 @@ import { expandTilde } from './utils/pathUtils';
import log from './utils/logger';
import { ensureWinShims } from './utils/winShims';
import { addRecentDir, loadRecentDirs } from './utils/recentDirs';
import { formatAppName } from './utils/conversionUtils';
import { formatAppName, errorMessage } from './utils/conversionUtils';
import type { Settings } from './utils/settings';
import { defaultKeyboardShortcuts, getKeyboardShortcuts } from './utils/settings';
import * as crypto from 'crypto';
@@ -1073,8 +1073,7 @@ function parseRecipeDeeplink(url: string): RecipeDeeplinkData | undefined {
try {
recipeDeeplink = decodeURIComponent(recipeDeeplinkTmp);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error('[Main] parseRecipeDeeplink - Failed to decode:', errorMessage);
console.error('[Main] parseRecipeDeeplink - Failed to decode:', errorMessage(error));
return undefined;
}
}
+5 -3
View File
@@ -1,5 +1,6 @@
import { fetchSharedSessionDetails, SharedSessionDetails } from './sharedSessions';
import { View, ViewOptions } from './utils/navigationUtils';
import { errorMessage } from './utils/conversionUtils';
/**
* Handles opening a shared session from a deep link
@@ -61,13 +62,14 @@ export async function openSharedSessionFromDeepLink(
return sessionDetails;
} catch (error) {
const errorMessage = `Failed to open shared session: ${error instanceof Error ? error.message : 'Unknown error'}`;
console.error(errorMessage);
const errMsg = errorMessage(error, 'Unknown error');
const fullErrorMessage = `Failed to open shared session: ${errMsg}`;
console.error(fullErrorMessage);
// Navigate to the shared session view with the error instead of throwing
setView('sharedSession', {
sessionDetails: null,
error: error instanceof Error ? error.message : 'Unknown error',
error: errMsg,
shareToken: url.replace('goose://sessions/', ''),
baseUrl,
});
+7 -6
View File
@@ -16,6 +16,7 @@ import * as fs from 'fs/promises';
import log from './logger';
import { githubUpdater } from './githubUpdater';
import { loadRecentDirs } from './recentDirs';
import { errorMessage } from './conversionUtils';
import {
trackUpdateCheckStarted,
trackUpdateCheckCompleted,
@@ -99,7 +100,7 @@ export function registerUpdateIpcHandlers() {
log.error(`=== MANUAL UPDATE CHECK FAILED after ${duration}ms ===`);
log.error('Error checking for updates:', error);
log.error('Manual check error details:', {
message: error instanceof Error ? error.message : 'Unknown error',
message: errorMessage(error, 'Unknown error'),
stack: error instanceof Error ? error.stack : 'No stack',
name: error instanceof Error ? error.name : 'Unknown',
code:
@@ -189,12 +190,12 @@ export function registerUpdateIpcHandlers() {
trackUpdateCheckCompleted('error', currentVersion, {
usingFallback: false,
errorType: error instanceof Error ? error.message : 'unknown',
errorType: errorMessage(error, 'unknown'),
});
return {
updateInfo: null,
error: error instanceof Error ? error.message : 'Unknown error',
error: errorMessage(error, 'Unknown error'),
};
}
});
@@ -250,11 +251,11 @@ export function registerUpdateIpcHandlers() {
false,
version,
method,
error instanceof Error ? error.message : 'unknown'
errorMessage(error, 'unknown')
);
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
error: errorMessage(error, 'Unknown error'),
};
}
});
@@ -708,7 +709,7 @@ async function githubAutoDownload(
false,
latestVersion,
'github-fallback',
downloadError instanceof Error ? downloadError.message : 'unknown'
errorMessage(downloadError, 'unknown')
);
log.error(
`Error during GitHub auto-download${contextLabel ? ` (${contextLabel})` : ''}:`,
+5 -5
View File
@@ -4,7 +4,7 @@ import * as fs from 'fs/promises';
import * as path from 'path';
import * as os from 'os';
import log from './logger';
import { safeJsonParse } from './conversionUtils';
import { safeJsonParse, errorMessage } from './conversionUtils';
interface GitHubRelease {
tag_name: string;
@@ -142,7 +142,7 @@ export class GitHubUpdater {
} catch (error) {
log.error('GitHubUpdater: Error checking for updates:', error);
log.error('GitHubUpdater: Error details:', {
message: error instanceof Error ? error.message : 'Unknown error',
message: errorMessage(error, 'Unknown error'),
stack: error instanceof Error ? error.stack : 'No stack',
name: error instanceof Error ? error.name : 'Unknown',
code:
@@ -152,7 +152,7 @@ export class GitHubUpdater {
});
return {
updateAvailable: false,
error: error instanceof Error ? error.message : 'Unknown error',
error: errorMessage(error, 'Unknown error'),
};
}
}
@@ -271,13 +271,13 @@ export class GitHubUpdater {
log.error(`=== GitHubUpdater: DOWNLOAD FAILED after ${duration}ms ===`);
log.error('GitHubUpdater: Error downloading update:', error);
log.error('GitHubUpdater: Download error details:', {
message: error instanceof Error ? error.message : 'Unknown error',
message: errorMessage(error, 'Unknown error'),
stack: error instanceof Error ? error.stack : 'No stack',
name: error instanceof Error ? error.name : 'Unknown',
});
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
error: errorMessage(error, 'Unknown error'),
};
}
}
+3 -1
View File
@@ -1,3 +1,5 @@
import { errorMessage } from './conversionUtils';
const DEFAULT_OLLAMA_HOST = 'http://127.0.0.1:11434';
const OLLAMA_DOWNLOAD_URL = 'https://ollama.com/download';
const PREFERRED_MODEL = 'gpt-oss:20b';
@@ -52,7 +54,7 @@ export async function checkOllamaStatus(): Promise<OllamaStatus> {
return {
isRunning: false,
host: DEFAULT_OLLAMA_HOST,
error: error instanceof Error ? error.message : 'Unknown error',
error: errorMessage(error, 'Unknown error'),
};
}
}
+2 -4
View File
@@ -1,5 +1,6 @@
import { Session } from '../api';
import { getApiUrl } from '../config';
import { errorMessage } from './conversionUtils';
/**
* In-memory cache for session data
@@ -57,10 +58,7 @@ export async function loadSession(sessionId: string, forceRefresh = false): Prom
return session;
} catch (error) {
if (error instanceof Error) {
throw new Error(`Error loading session ${sessionId}: ${error.message}`);
}
throw new Error(`Error loading session ${sessionId}: Unknown error`);
throw new Error(`Error loading session ${sessionId}: ${errorMessage(error, 'Unknown error')}`);
} finally {
inFlightRequests.delete(sessionId);
}