Skip to content

fix: prevent duplicate chatflow creation on repeated save clicks#6553

Open
putramkti wants to merge 1 commit into
FlowiseAI:mainfrom
putramkti:bugfix/duplicate-chatflow-on-repeated-click
Open

fix: prevent duplicate chatflow creation on repeated save clicks#6553
putramkti wants to merge 1 commit into
FlowiseAI:mainfrom
putramkti:bugfix/duplicate-chatflow-on-repeated-click

Conversation

@putramkti

Copy link
Copy Markdown

Problem

Rapidly clicking the Save button on the canvas (or pressing the keyboard shortcut multiple times) fires multiple concurrent createNewChatflow API calls, resulting in duplicate chatflows being created. This affects both the regular canvas and the AgentFlow V2 canvas.

Fix

Add a loading-state guard at three levels to prevent re-entrant save operations:

  1. handleSaveFlow in both Canvas and AgentflowCanvas — early-return if a save request is already in flight
  2. CanvasHeader — receive isSaving prop, disable the save button visually, and guard both onSaveChatflowClick and onConfirmSaveName handlers
  const handleSaveFlow = (chatflowName) => {
+     if (createNewChatflowApi.loading) return
      if (reactFlowInstance) { ... }
  }
- <ButtonBase title={`Save ${title}`} sx={{ borderRadius: '50%', mr: 2 }}>
+ <ButtonBase title={`Save ${title}`} disabled={isSaving} sx={{ borderRadius: '50%', mr: 2 }}>

Scope

  • packages/ui/src/views/canvas/index.jsx (modified, +2/-0)
  • packages/ui/src/views/canvas/CanvasHeader.jsx (modified, +4/-2)
  • packages/ui/src/views/agentflowsv2/Canvas.jsx (modified, +2/-0)

Testing

  • Verified that clicking Save multiple times in quick succession only creates one chatflow.
  • Verified that the Save button is visually disabled while a save request is in progress.
  • Verified that normal single-click save still works as expected.

Guard handleSaveFlow with a loading check so rapid clicks cannot
queue multiple create requests. Disable the save button in
CanvasHeader while a save is in progress.

Fixes FlowiseAI#6502

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

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.

Code Review

This pull request introduces guards and UI-level disabling to prevent duplicate or concurrent saving of chatflows by checking the createNewChatflowApi.loading state and passing it as isSaving to the CanvasHeader. The feedback recommends extending these guards to also check for updateChatflowApi.loading (and getHasChatflowChangedApi.loading where applicable) to ensure that updating existing flows is similarly protected against concurrent requests.

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.

}

const handleSaveFlow = (chatflowName) => {
if (createNewChatflowApi.loading) return

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

The current guard only checks createNewChatflowApi.loading, which prevents duplicate requests when creating a new flow. However, if the user is updating an existing flow, updateChatflowApi is used instead. To prevent concurrent update requests, we should guard against both loading states.

Suggested change
if (createNewChatflowApi.loading) return
if (createNewChatflowApi.loading || updateChatflowApi.loading) return

<CanvasHeader
chatflow={chatflow}
handleSaveFlow={handleSaveFlow}
isSaving={createNewChatflowApi.loading}

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

Pass both createNewChatflowApi.loading and updateChatflowApi.loading to isSaving so that the save button is also disabled during update operations.

Suggested change
isSaving={createNewChatflowApi.loading}
isSaving={createNewChatflowApi.loading || updateChatflowApi.loading}

}

const handleSaveFlow = async (chatflowName) => {
if (createNewChatflowApi.loading) return

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

Similar to the agentflow canvas, the guard here should also prevent concurrent saves when updating an existing flow. Since the update flow in this canvas involves checking if the chatflow has changed first, we should guard against createNewChatflowApi.loading, updateChatflowApi.loading, and getHasChatflowChangedApi.loading.

Suggested change
if (createNewChatflowApi.loading) return
if (createNewChatflowApi.loading || updateChatflowApi.loading || getHasChatflowChangedApi.loading) return

<CanvasHeader
chatflow={chatflow}
handleSaveFlow={handleSaveFlow}
isSaving={createNewChatflowApi.loading}

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

Pass all relevant loading states to isSaving to ensure the save button is disabled during both creation and update operations.

Suggested change
isSaving={createNewChatflowApi.loading}
isSaving={createNewChatflowApi.loading || updateChatflowApi.loading || getHasChatflowChangedApi.loading}

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.

1 participant