Skip to content

fix: target the correct HIL action when clearing pending messages#6615

Open
sanahkapoor wants to merge 1 commit into
FlowiseAI:mainfrom
sanahkapoor:bugfix/hil-action-target-wrong-node
Open

fix: target the correct HIL action when clearing pending messages#6615
sanahkapoor wants to merge 1 commit into
FlowiseAI:mainfrom
sanahkapoor:bugfix/hil-action-target-wrong-node

Conversation

@sanahkapoor

Copy link
Copy Markdown

Summary

Fixes incorrect action clearing when multiple Human-In-The-Loop (HIL) nodes have pending actions.

The server previously selected a pending action by message position, while the UI always cleared the last message. This could target the wrong HIL action when multiple approvals were pending.

Changes

  • Match server-side pending actions using the HIL node ID
  • Match UI actions using the action ID
  • Add unit tests for multiple pending HIL actions and edge cases

Testing

  • Added 6 unit tests for HIL action matching
  • Server typecheck passes
  • Verified the targeted action-matching behavior against a local SQLite reproduction

Addresses #4787

…ctions

When an agentflow contains more than one Human-In-The-Loop (Proceed/Reject)
node, more than one chat message can have a pending action at the same time.

Both the resume handler and the frontend button handler assumed there was
only ever one pending action and located it positionally (the most
recently created message with an action on the server, the last message
in the list on the client) instead of by identity. Resolving one HIL node
would therefore clear the wrong message's action, making it look like
every other pending HIL block had also been actioned.

- server: extract findChatMessageActionToClear() and match on
  humanInput.startNodeId instead of taking the newest message with any
  action.
- ui: match the clicked action's id against message.action.id instead of
  always clearing the last message in the array.

Fixes FlowiseAI#4787

@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 addresses an issue where multiple Human-In-The-Loop (HIL) nodes are pending simultaneously. It ensures that resuming a node clears the action on the specific message tied to that node rather than simply clearing the newest pending action. This logic is updated in both the backend flow execution and the frontend chat interface, supported by new unit tests. Feedback on the frontend changes points out a potential bug where comparing action IDs directly could lead to incorrect matches (e.g., if both IDs are undefined or if one action is a string and the other is an object), and recommends using a robust helper function to safely parse and compare the IDs.

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.

allMessages[allMessages.length - 1].action = null
// Clear the action on the message this button belongs to, not just the last message - a flow
// can have multiple pending HIL nodes at once. See #4787.
const targetIndex = allMessages.findIndex((msg) => msg.action && action && msg.action.id === action.id)

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.

high

Issue: Potential incorrect matching or runtime errors when comparing action IDs

There are two main concerns with the current comparison logic:

  1. Accidental matches on undefined: If both msg.action and action are objects but neither has an id property (or if they are both strings, making .id evaluate to undefined), msg.action.id === action.id will evaluate to true (since undefined === undefined is true). This can cause the wrong message's action to be cleared.
  2. Mixed types (String vs. Object): Depending on whether the message was loaded from history or newly streamed, msg.action and action can be either a JSON string or a parsed object. If one is a string and the other is an object, comparing .id directly will fail to match.

Recommendation

Implement a robust helper to safely extract the action ID, handling both stringified and parsed object formats, and explicitly verify that both IDs are defined before comparing them.

            const getActionId = (act) => {
                if (!act) return null
                if (typeof act === 'string') {
                    try {
                        return JSON.parse(act)?.id
                    } catch {
                        return null
                    }
                }
                return act.id
            }
            const targetActionId = getActionId(action)
            const targetIndex = allMessages.findIndex((msg) => {
                const msgActionId = getActionId(msg.action)
                return !!(msgActionId && targetActionId && msgActionId === targetActionId)
            })
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.

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