Skip to content

DataGridView can crash dialogs with "Cannot have two HTML5 backends at the same time" #10485

Description

@kundansable

Describe the bug

DataGridView wraps its table in <DndProvider backend={HTML5Backend}> (web/pgadmin/static/js/SchemaView/DataGridView/grid.jsx). With the plain backend prop, react-dnd 16 keeps the HTML5 backend on a global singleton guarded by a module-level refCount.

pgAdmin mounts dialogs in separate ReactDOM.createRoot roots. If one root's DndProvider unmounts and refCount reaches 0, react-dnd nulls the singleton, but the backend may still be attached to window and in use by a grid in another root. The next grid then builds a fresh backend. Its setup() sees __isReactDndBackendSetUp already set and throws. React's ErrorBoundary then renders "Something went wrong." in place of the dialog contents.

This is a known react-dnd issue (react-dnd/react-dnd#3178). react-arborist also bundles its own dnd-core 14, which sits at the top level of node_modules, so react-dnd 16 ends up with a nested dnd-core 16.

To Reproduce

The trigger is a DataGridView with reorderable rows plus a react-arborist tree (PgTreeView) open at the same time, then closing one of them. It is deterministic, not timing-dependent. react-arborist bundles react-dnd 14, which stores its manager under the same global key as react-dnd 16 but keeps a separate reference count. Whichever one drops to zero nulls the shared manager while the other still has the HTML5 backend set up on window.

The columns grid only registers drag sources when rows can be reordered (canReorder, which is true for a new table). In the Preferences dialog, the left-hand category tree is a PgTreeView.

Order A: tree first

  1. Open File > Preferences and leave the Preferences tab open.
  2. In the Object Explorer, right-click Tables under a schema and choose Create > Table....
  3. Go to the Columns tab and click + to add a column. Leave this dialog open.
  4. Close the Preferences tab.
  5. Open a second Create > Table... dialog, go to Columns, and click +.
  6. The second dialog's body shows "Something went wrong." and the console logs Error: Cannot have two HTML5 backends at the same time., coming from <DataGridRow>.

Order B: grid first

  1. Open Create > Table..., go to Columns, and click + to add a column.
  2. Open File > Preferences and leave it open.
  3. Close the Create Table dialog.
  4. Open Create > Table... again, go to Columns, and click +. You get the same error.

Both orders are reproduced as automated tests in regression/javascript/SchemaView/DataGridViewDnd.spec.js (see the "DataGridView together with PgTreeView" tests). On master they fail with exactly this error. The UI steps above are derived from that reproduction and the code paths. They have not yet been run manually in a browser.

Expected behavior

The dialog and its grid render normally every time.

Error message

Error: Cannot have two HTML5 backends at the same time.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions