Skip to content

fix(ui): guard missing Axios error.response in ToolDialog error handlers#6482

Open
chatman-media wants to merge 2 commits into
FlowiseAI:mainfrom
chatman-media:fix/axios-error-response-guard
Open

fix(ui): guard missing Axios error.response in ToolDialog error handlers#6482
chatman-media wants to merge 2 commits into
FlowiseAI:mainfrom
chatman-media:fix/axios-error-response-guard

Conversation

@chatman-media
Copy link
Copy Markdown

Closes #6466

Problem

Catch blocks in packages/ui/src/views/tools/ToolDialog.jsx access error.response.data without checking whether error.response exists first:

// before — crashes when error.response is undefined
typeof error.response.data === 'object' ? error.response.data.message : error.response.data

Axios only sets error.response when the server actually returned an HTTP response. On network failures, timeouts, CORS blocks, and cancelled requests error.response is undefined, so the code above throws a secondary TypeError inside the catch block itself. This masks the real failure and leaves the user with no toast notification.

Fix

1. packages/ui/src/utils/errorHandler.js — adds getAxiosErrorMessage(error):

export const getAxiosErrorMessage = (error) => {
    if (error?.response?.data) {
        const data = error.response.data
        if (typeof data === 'object') {
            return data.message || data.error || getErrorMessage(error)
        }
        return String(data)
    }
    return error?.message || 'An unexpected error occurred'
}

Priority: response.data.messageresponse.data.error → plain string body → error.message → generic fallback. Never assumes response is defined.

2. packages/ui/src/views/tools/ToolDialog.jsx — replaces all four unsafe accesses (in exportTool, addNewTool, saveTool, deleteTool) with getAxiosErrorMessage(error).

3. packages/ui/src/utils/errorHandler.test.js — adds 10 focused unit tests:

  • safe fallback when error.response is undefined
  • safe fallback when error is null / undefined
  • extracts response.data.message (structured API error)
  • extracts response.data.error
  • returns plain string body
  • falls back to error.message
  • generic fallback when nothing is present

Verification

All 10 unit tests pass (jest --testPathPattern=errorHandler.test):

PASS packages/ui/src/utils/errorHandler.test.js
  getErrorMessage
    ✓ returns the message from an Error object
    ✓ serialises a plain object when it has no message property
  getAxiosErrorMessage
    ✓ returns a safe fallback when error.response is undefined (network failure / timeout / CORS)
    ✓ returns a safe fallback when the error itself is undefined
    ✓ returns a safe fallback when the error is null
    ✓ extracts response.data.message when the server returns a structured error
    ✓ extracts response.data.error when only that key is present
    ✓ returns a plain string response body as-is
    ✓ falls back to error.message when response.data is falsy
    ✓ returns the generic fallback when there is no message at all

Tests: 10 passed, 10 total

Prettier reports all changed files as (unchanged) — style already conforms to the project config.

🤖 Generated with Claude Code

When a network request fails at the transport level (timeout, CORS block,
cancelled request, offline) Axios sets error.response to undefined.
Catch blocks in ToolDialog.jsx read error.response.data directly, so a
secondary TypeError is thrown inside the error handler itself, masking
the real failure and leaving users with no feedback.

Changes:
- Add getAxiosErrorMessage() to packages/ui/src/utils/errorHandler.js.
  It safely extracts a message by checking response?.data?.message,
  response?.data?.error, a plain string body, then error.message, and
  finally a generic fallback — never assuming response is defined.
- Replace all four bare error.response.data accesses in
  packages/ui/src/views/tools/ToolDialog.jsx (exportTool, addNewTool,
  saveTool, deleteTool) with getAxiosErrorMessage(error).
- Add packages/ui/src/utils/errorHandler.test.js with 10 unit tests
  covering the new helper (undefined response, null error, structured
  data, plain string body, generic fallback).

Closes FlowiseAI#6466
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a centralized getAxiosErrorMessage utility function to safely extract human-readable messages from Axios errors, along with a comprehensive suite of unit tests. It also refactors ToolDialog.jsx to replace repetitive inline error-handling logic with this new utility. Feedback on the PR suggests making the getAxiosErrorMessage function more robust by handling nested error objects and array messages to prevent rendering issues like [object Object] in the UI.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +37 to +46
export const getAxiosErrorMessage = (error) => {
if (error?.response?.data) {
const data = error.response.data
if (typeof data === 'object') {
return data.message || data.error || getErrorMessage(error)
}
return String(data)
}
return error?.message || 'An unexpected error occurred'
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the API returns a nested error object (e.g., { error: { message: '...' } } which is common in OpenAI and other standard APIs) or an array of messages (e.g., ['error 1', 'error 2'] in NestJS validation errors), the current implementation will return the object or array directly. When interpolated into a string in the UI, this results in [object Object] or unformatted output.

We can make getAxiosErrorMessage more robust by safely resolving nested error objects and joining array messages with commas.

Suggested change
export const getAxiosErrorMessage = (error) => {
if (error?.response?.data) {
const data = error.response.data
if (typeof data === 'object') {
return data.message || data.error || getErrorMessage(error)
}
return String(data)
}
return error?.message || 'An unexpected error occurred'
}
export const getAxiosErrorMessage = (error) => {
if (error?.response?.data) {
const data = error.response.data
if (typeof data === 'object' && data !== null) {
const rawMessage = data.message || (typeof data.error === 'object' ? data.error?.message || data.error?.error : data.error)
if (rawMessage) {
if (Array.isArray(rawMessage)) {
return rawMessage.join(', ')
}
if (typeof rawMessage === 'object') {
return JSON.stringify(rawMessage)
}
return String(rawMessage)
}
return getErrorMessage(error)
}
return String(data)
}
return error?.message || 'An unexpected error occurred'
}
References
  1. When using a heuristic for detection (e.g., for content type), ensure a safe fallback mechanism is in place to correctly handle cases where the heuristic fails.

…ssage

Handle APIs that nest the message ({ error: { message } }) or return an array of
messages (NestJS validation) so the UI never renders [object Object].

Addresses gemini-code-assist review on FlowiseAI#6466
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug : Frontend API error handling can crash when Axios error.response is missing

1 participant