Skip to content

fix: resolve custom tool input schema persistence race condition#5885

Open
DiveshK007 wants to merge 2 commits intoFlowiseAI:mainfrom
DiveshK007:fix/custom-tool-schema-persistence
Open

fix: resolve custom tool input schema persistence race condition#5885
DiveshK007 wants to merge 2 commits intoFlowiseAI:mainfrom
DiveshK007:fix/custom-tool-schema-persistence

Conversation

@DiveshK007
Copy link

@DiveshK007 DiveshK007 commented Mar 3, 2026

Fixes #5761

MUI DataGrid defers state updates when a cell is still in edit mode. Clicking Save without blurring caused stale schema state to be serialized, making edits appear to revert.

Force-commit pending cell edits before save, stabilize row identity, and serialize schema using the latest state.

MUI DataGrid defers state updates when a cell is still in edit mode.
Clicking Save without blurring caused stale schema state to be serialized,
making edits appear to revert.

Force-commit pending cell edits before save, stabilize row identity,
and serialize schema using the latest state.
Copilot AI review requested due to automatic review settings March 3, 2026 18:08
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the reliability of custom tool input schema persistence. By proactively handling MUI DataGrid's asynchronous state updates and ensuring data integrity through stable row identification and robust validation, it prevents data loss and inconsistent behavior when users edit and save tool schemas.

Highlights

  • Race Condition Resolution: Addressed a race condition where MUI DataGrid's deferred state updates caused stale schema data to be serialized if 'Save' was clicked before cells blurred, leading to reverted edits.
  • Forced Edit Commit: Implemented a mechanism to force-commit any pending cell edits in the MUI DataGrid before saving, ensuring the latest user input is captured.
  • Stable Row Identity: Introduced UUIDs for DataGrid rows to provide stable and unique identifiers, improving reconciliation and preventing issues with row updates.
  • Schema Serialization and Validation: Refactored schema serialization to use a useRef for the latest state and added pre-save validation for property names (empty or duplicates).
Changelog
  • packages/ui/src/ui-component/grid/Grid.jsx
    • Added apiRef prop to the Grid component to allow external control over the DataGrid API.
  • packages/ui/src/views/tools/PasteJSONDialog.jsx
    • Imported uuidv4 for generating unique IDs for schema items.
    • Updated schema item ID generation to use uuidv4 instead of sequential numbers.
    • Added trimming to the property field when parsing pasted JSON.
  • packages/ui/src/views/tools/ToolDialog.jsx
    • Imported useRef, useGridApiRef, and uuidv4 for state management and unique ID generation.
    • Removed cloneDeep and formatDataGridRows utility imports.
    • Introduced a new formatSchemaRows utility function to convert stored schema rows into DataGrid-compatible rows with stable UUIDs and normalized types.
    • Added toolSchemaRef using useRef to always mirror the latest toolSchema state, addressing asynchronous update issues.
    • Initialized gridApiRef using useGridApiRef to gain programmatic control over the MUI DataGrid.
    • Modified addNewRow to assign a uuidv4 to new schema rows.
    • Implemented commitPendingEdits function to programmatically stop cell edit mode in the DataGrid and wait for state updates to flush.
    • Created serializeSchema function to clean and stringify the schema for storage, reading from toolSchemaRef.
    • Developed getSchemaValidationError function to validate schema rows for empty or duplicate property names before saving.
    • Updated onSaveAsTemplate, addNewTool, and saveTool functions to call commitPendingEdits and getSchemaValidationError before proceeding with serialization and API calls.
    • Modified onRowUpdate to update rows immutably, trim property values, normalize types, and eagerly sync toolSchemaRef.
    • Replaced calls to formatDataGridRows with the new formatSchemaRows when initializing toolSchema.
    • Passed gridApiRef to the Grid component to enable external API control.
Activity
  • No human activity has occurred on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
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 effectively resolves a race condition with custom tool input schema persistence by force-committing pending edits from the MUI DataGrid before saving. The use of a ref to hold the latest state, stabilizing row identities with UUIDs, and adding pre-save validation are all excellent improvements. My only feedback is a suggestion to refactor some duplicated code to enhance maintainability.

Comment on lines +431 to +448
await commitPendingEdits()
const schemaError = getSchemaValidationError()
if (schemaError) {
enqueueSnackbar({
message: schemaError,
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
persist: true,
action: (key) => (
<Button style={{ color: 'white' }} onClick={() => closeSnackbar(key)}>
<IconX />
</Button>
)
}
})
return
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This validation and error handling block is identical to the one in the addNewTool function (lines 367-384). To improve code quality and maintainability, this duplicated logic should be extracted into a shared helper function. This would centralize the error handling and make future changes easier.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a race where MUI DataGrid edits weren’t committed before persisting a custom tool’s input schema, leading to stale schema serialization when users click Save without blurring the edited cell.

Changes:

  • Adds a DataGrid apiRef and a commitPendingEdits() step to force-commit in-progress cell edits prior to saving/exporting.
  • Switches schema row identity to UUIDs and introduces schema (de)serialization helpers (formatSchemaRows, serializeSchema) with normalization.
  • Adds schema validation on save (empty property + duplicate property names).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/ui/src/views/tools/ToolDialog.jsx Forces edit commit before save/export, stabilizes row IDs, serializes schema from “latest” state, and validates schema.
packages/ui/src/views/tools/PasteJSONDialog.jsx Generates UUID row IDs for pasted schema and normalizes/cleans pasted properties.
packages/ui/src/ui-component/grid/Grid.jsx Extends shared Grid wrapper to accept and pass through MUI DataGrid apiRef.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +112 to +118
// Ref that always mirrors the latest toolSchema state.
// Needed because MUI DataGrid's processRowUpdate → onRowUpdate uses setTimeout,
// so React state may not yet reflect the latest edit when Save is clicked.
const toolSchemaRef = useRef(toolSchema)
useEffect(() => {
toolSchemaRef.current = toolSchema
}, [toolSchema])
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

toolSchemaRef is kept in sync via useEffect, which runs after paint. Because serializeSchema()/getSchemaValidationError() read from the ref, there’s still a window where the UI has rendered the latest toolSchema but the ref hasn’t been updated yet, so a fast click on Save/Save As Template could serialize stale schema. Consider syncing this ref in a useLayoutEffect, or updating toolSchemaRef.current inside every setToolSchema call (not just onRowUpdate) so it is always current before any save handler runs.

Copilot uses AI. Check for mistakes.
Comment on lines +176 to +184
const commitPendingEdits = async () => {
try {
const editRowsModel = gridApiRef.current?.state?.editRows
if (editRowsModel) {
for (const rowId of Object.keys(editRowsModel)) {
for (const field of Object.keys(editRowsModel[rowId])) {
try {
gridApiRef.current.stopCellEditMode({ id: rowId, field })
} catch (_) {
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

commitPendingEdits reads gridApiRef.current.state.editRows, which is an internal DataGrid state shape and can change across @mui/x-data-grid versions. Prefer a public apiRef method/selector (if available in 6.8.0) to get the current edit model, or encapsulate this behind a small helper with a comment tying it to the specific MUI version to reduce upgrade risk.

Copilot uses AI. Check for mistakes.
@HenryHengZJ HenryHengZJ added the ui Issues or features related to ui label Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ui Issues or features related to ui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom tool edit does not work

3 participants