Skip to content

[Flyout System] Prevent race condition crash when closing managed flyouts#9356

Merged
tsullivan merged 9 commits intoelastic:mainfrom
tsullivan:flyout-system/use-flush-sync
Feb 6, 2026
Merged

[Flyout System] Prevent race condition crash when closing managed flyouts#9356
tsullivan merged 9 commits intoelastic:mainfrom
tsullivan:flyout-system/use-flush-sync

Conversation

@tsullivan
Copy link
Copy Markdown
Member

@tsullivan tsullivan commented Feb 4, 2026

Summary

Follows #9346
Re-close elastic/kibana#250177

Fix: Prevent race condition crash when closing managed flyouts

Fixes a production-only crash (NotFoundError: Failed to execute 'insertBefore') that occurred when closing overlay flyouts in rapid succession.

Root Cause:

  • Component re-registered itself during unmount because of a state variable used in the dependencies of a useEffect (flyoutExistsInManager)
  • Asynchronous state updates created conflict with synchronous DOM cleanup
  • Race condition only manifested in production builds due to React's batching behavior

Changes:

  1. Use flushSync in the onClose handler to force synchronous state update completion before the DOM cleanup
  2. Switch to useLayoutEffect for synchronously registering the flyout with the manager before DOM updates. All lifecycle management (setup and cleanup) is consolidated into this effect.
  3. Create a ref around flyoutExistsInManager to prevent re-registration loops during cleanup
  4. Remove duplicate cleanup effect

Why are we making this change?

Stability / bug fix

Screenshots #

The original bug was only evident when running with a production build in Kibana, because that environment leverages batched React updates. The test case from these recordings uses a Kibana build with a hacked Home page to showcasing a flyout button to exhibit a crash problem.

  • Before
before.-.Screen.Recording.2026-02-04.at.3.23.15.PM.mov
  • After
after.-.Screen.Recording.2026-02-04.at.3.23.15.PM.mov

Impact to users

Testing

  1. Create a build of EUI with this branch
  2. Set up Kibana to test the EUI build locally
  3. Create a Flyout System button on the Kibana home page (Kibana example plugins will not be visible when running from a build)
  4. Create a build of Kibana
  5. Run the build
  6. Test the flyouts

Or build and test this Kibana branch: https://github.com/tsullivan/kibana/tree/test-eui-9346

QA

Remove or strikethrough items that do not apply to your PR.

General checklist

  • Browser QA
    • [ ] Checked in both light and dark modes
    • [ ] Checked in both MacOS and Windows high contrast modes
    • [ ] Checked in mobile
    • Checked in Chrome, Safari, Edge, and Firefox
    • Checked for accessibility including keyboard-only and screenreader modes
  • Docs site QA
  • Code quality checklist
  • Release checklist
    • [ ] A changelog entry exists and is marked appropriately
    • [ ] If applicable, added the breaking change issue label (and filled out the breaking change checklist)
    • [ ] If the changes unblock an issue in a different repo, smoke tested carefully (see Testing EUI features in Kibana ahead of time)
  • Designer checklist
    • [ ] If applicable, file an issue to update EUI's Figma library with any corresponding UI changes. (This is an internal repo, if you are external to Elastic, ask a maintainer to submit this request)

@tsullivan tsullivan force-pushed the flyout-system/use-flush-sync branch from 37029b9 to a00cd56 Compare February 4, 2026 23:03
@tsullivan tsullivan force-pushed the flyout-system/use-flush-sync branch from a00cd56 to 8025326 Compare February 4, 2026 23:04
}
}, [currentSession, flyoutId, level]);

useEffect(() => {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This secondary useEffect was a duplicate cleanup effect. It was removed because it was redundant: there already is a cleanup function in the primary effect on lines 188-204 ('useLayoutEffect`).

@tsullivan tsullivan marked this pull request as ready for review February 4, 2026 23:11
@tsullivan tsullivan requested a review from a team as a code owner February 4, 2026 23:11
@tsullivan tsullivan added the skip-changelog Use on PRs to skip changelog requirement (Don't delete - used for automation) label Feb 4, 2026
@acstll acstll self-requested a review February 6, 2026 08:02
Copy link
Copy Markdown
Contributor

@acstll acstll left a comment

Choose a reason for hiding this comment

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

🟢 Tested the code locally, using your branch, with a build of Kibana, and can confirm the changes fix the issues.

Only leaving a comment on the test file. Everything else in the code looks good to me. Thank you @tsullivan

@tsullivan tsullivan enabled auto-merge (squash) February 6, 2026 15:42
@acstll acstll disabled auto-merge February 6, 2026 15:46
@acstll
Copy link
Copy Markdown
Contributor

acstll commented Feb 6, 2026

@tsullivan this being a bug fix going into main, was it intentional to skip the changelog entry? (sorry I disabled auto-merge!)

@tsullivan tsullivan removed the skip-changelog Use on PRs to skip changelog requirement (Don't delete - used for automation) label Feb 6, 2026
@tsullivan tsullivan enabled auto-merge (squash) February 6, 2026 16:10
@elasticmachine
Copy link
Copy Markdown
Collaborator

💚 Build Succeeded

History

@elasticmachine
Copy link
Copy Markdown
Collaborator

💚 Build Succeeded

History

@tsullivan tsullivan merged commit 9553e5d into elastic:main Feb 6, 2026
6 checks passed
mgadewoll added a commit to elastic/kibana that referenced this pull request Feb 10, 2026
## Dependency updates

- `@elastic/eui`: v112.2.0 ⏩ v112.3.0
- `@elastic/eslint-plugin-eui`: v2.7.0 ⏩ v2.8.0

---

## Package updates

### `@elastic/eui`
[v112.3.0](https://github.com/elastic/eui/releases/tag/v112.3.0)

- Added new `server` icon.
([#9355](elastic/eui#9355))
- Added `className` support to `EuiMarkdownEditor`'s `toolbarProps` for
custom toolbar styling
([#9349](elastic/eui#9349))
- Updated `EuiFilePicker` to use the `upload` icon to better indicate
uploads. ([#9351](elastic/eui#9351))
- Exported the flyout system store singleton and added an event observer
for emitting close session events
([#9347](elastic/eui#9347))
- Updated `EuiIcon` to use standard dynamic imports for icon assets,
enabling native support for modern bundlers (Rollup, Parcel) and
improving initial load performance
([#9342](elastic/eui#9342))

**Bug fixes**

- Fixed a potential crash in the flyout system: due to asynchronous
state updates and React's batching behavior, it was possible to
experience a crash when closing a managed flyout.
([#9356](elastic/eui#9356))

### `@elastic/eslint-plugin-eui` v2.8.0

- Added new `icon-accessibility-rules` rule.
([#9357](elastic/eui#9357))
- Added new `badge-accessibility-rules` rule.
([#9354](elastic/eui#9354))
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️⃣ [Discover][Traces] Investigate white screen crash when closing nested flyouts in builds

4 participants