diff --git a/packages/ui/src/utils/errorHandler.js b/packages/ui/src/utils/errorHandler.js index 17aae836fd1..0ad1d3226ed 100644 --- a/packages/ui/src/utils/errorHandler.js +++ b/packages/ui/src/utils/errorHandler.js @@ -14,6 +14,31 @@ const toErrorWithMessage = (maybeError) => { } } +const getAxiosErrorMessage = (error) => { + const responseData = error?.response?.data + + if (typeof responseData === 'string') return responseData + + if (responseData && typeof responseData === 'object') { + if (typeof responseData.message === 'string') return responseData.message + if (Array.isArray(responseData.message)) return responseData.message.join(', ') + if (typeof responseData.error === 'string') return responseData.error + + try { + return JSON.stringify(responseData) + } catch { + return undefined + } + } + + if (error?.response?.status) { + return `${error.response.status}${error.response.statusText ? ` ${error.response.statusText}` : ''}` + } +} + export const getErrorMessage = (error) => { + const axiosErrorMessage = getAxiosErrorMessage(error) + if (axiosErrorMessage) return axiosErrorMessage + return toErrorWithMessage(error).message } diff --git a/packages/ui/src/utils/errorHandler.test.js b/packages/ui/src/utils/errorHandler.test.js new file mode 100644 index 00000000000..bb8028e3373 --- /dev/null +++ b/packages/ui/src/utils/errorHandler.test.js @@ -0,0 +1,56 @@ +import { getErrorMessage } from './errorHandler' + +describe('getErrorMessage', () => { + it('uses an axios response data message when available', () => { + const error = { + message: 'Request failed with status code 400', + response: { + data: { + message: 'Tool name already exists' + } + } + } + + expect(getErrorMessage(error)).toBe('Tool name already exists') + }) + + it('uses an axios response data error when message is unavailable', () => { + const error = { + message: 'Request failed with status code 400', + response: { + data: { + error: 'Invalid tool schema' + } + } + } + + expect(getErrorMessage(error)).toBe('Invalid tool schema') + }) + + it('uses a string axios response body', () => { + const error = { + message: 'Request failed with status code 500', + response: { + data: 'Internal server error' + } + } + + expect(getErrorMessage(error)).toBe('Internal server error') + }) + + it('falls back to response status when response data is unavailable', () => { + const error = { + message: 'Request failed with status code 404', + response: { + status: 404, + statusText: 'Not Found' + } + } + + expect(getErrorMessage(error)).toBe('404 Not Found') + }) + + it('falls back to a regular error message when axios response is unavailable', () => { + expect(getErrorMessage(new Error('Network Error'))).toBe('Network Error') + }) +}) diff --git a/packages/ui/src/views/tools/ToolDialog.jsx b/packages/ui/src/views/tools/ToolDialog.jsx index b73b15ec19a..24781b79593 100644 --- a/packages/ui/src/views/tools/ToolDialog.jsx +++ b/packages/ui/src/views/tools/ToolDialog.jsx @@ -32,6 +32,7 @@ import useApi from '@/hooks/useApi' // utils import useNotifier from '@/utils/useNotifier' import { generateRandomGradient, formatDataGridRows } from '@/utils/genericHelper' +import { getErrorMessage } from '@/utils/errorHandler' import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from '@/store/actions' const exampleAPIFunc = `/* @@ -258,9 +259,7 @@ const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm, set } } catch (error) { enqueueSnackbar({ - message: `Failed to export Tool: ${ - typeof error.response.data === 'object' ? error.response.data.message : error.response.data - }`, + message: `Failed to export Tool: ${getErrorMessage(error)}`, options: { key: new Date().getTime() + Math.random(), variant: 'error', @@ -304,9 +303,7 @@ const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm, set } } catch (error) { enqueueSnackbar({ - message: `Failed to add new Tool: ${ - typeof error.response.data === 'object' ? error.response.data.message : error.response.data - }`, + message: `Failed to add new Tool: ${getErrorMessage(error)}`, options: { key: new Date().getTime() + Math.random(), variant: 'error', @@ -348,9 +345,7 @@ const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm, set } } catch (error) { enqueueSnackbar({ - message: `Failed to save Tool: ${ - typeof error.response.data === 'object' ? error.response.data.message : error.response.data - }`, + message: `Failed to save Tool: ${getErrorMessage(error)}`, options: { key: new Date().getTime() + Math.random(), variant: 'error', @@ -395,9 +390,7 @@ const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm, set } } catch (error) { enqueueSnackbar({ - message: `Failed to delete Tool: ${ - typeof error.response.data === 'object' ? error.response.data.message : error.response.data - }`, + message: `Failed to delete Tool: ${getErrorMessage(error)}`, options: { key: new Date().getTime() + Math.random(), variant: 'error',