Skip to content

[Bug]: ReferenceError: Property 'window' doesn't exist in useAnimatedLayout worklet on any Dimensions change (regression in 5.2.14) #2734

Description

@r8

Version

v5

Reanimated Version

v3

Gesture Handler Version

v2

Platforms

iOS, Android

What happened?

Since 5.2.14, mounting any BottomSheet/BottomSheetModal and triggering any Dimensions change event (keyboard show/hide, device rotation, app resume, window resize) crashes the Reanimated UI runtime:

ReferenceError: Property 'window' doesn't exist
    at gorhom_useAnimatedLayoutTs7

Root cause — regression introduced in 5853f117c8f0060e93b7284c123c0be9a06f337a ("fix: read window height from a shared value on ui thread", first released in v5.2.14, still present on master). In src/hooks/useAnimatedLayout.ts:

useEffect(() => {
  Dimensions.addEventListener('change', ({ window }) => {
    state.modify(_state => {
      'worklet';
      _state.window = window; // <-- throws on the UI runtime
      return _state;
    });
  });
}, [state]);

The destructured binding is named window, and Reanimated's Babel plugin lists window in its defaultGlobals (see react-native-reanimated/plugin). Identifiers in that list are treated as ambient globals and are never captured into the worklet closure, so on the native UI runtime — where no global window exists — the worklet throws the moment the listener fires. (gorhom_useAnimatedLayoutTs7 is exactly the 7th workletized function in that file, i.e. this state.modify callback.)

Because useAnimatedLayout runs for every sheet (BottomSheet.tsx), every consumer of 5.2.14 is affected; keyboard show/hide alone is enough to trigger it. 5.2.13 is unaffected (no window reference in that hook).

Suggested fix (one line) — rename the destructured binding so the plugin captures it:

Dimensions.addEventListener('change', ({ window: windowDimensions }) => {
  state.modify(_state => {
    'worklet';
    _state.window = windowDimensions;
    return _state;
  });
});

(While here: the effect never removes the listener — returning subscription.remove() would also fix a listener leak per mounted sheet.)

Previous reports of this same crash were auto-closed before triage: #2677, #2678, #2687, #2701, #2732.

Reproduction steps

  • yarn add @gorhom/bottom-sheet@5.2.14 (Reanimated 3.x, e.g. 3.19.5; new or old architecture — crash is in the worklet closure, not the renderer)
  • Mount a plain BottomSheet with any snapPoints
  • Run on an iOS or Android device/emulator
  • Trigger any Dimensions change event: focus a TextInput and dismiss the keyboard, rotate the device, or background/resume the app
  • App crashes with ReferenceError: Property 'window' doesn't exist
  • Downgrade to @gorhom/bottom-sheet@5.2.13 with the identical app code → no crash

Reproduction sample

https://snack.expo.dev/Yv3RU49EQK_Et3RBME3SF

Relevant log output

C++ Exception: N8facebook3jsi7JSErrorE: Property 'window' doesn't exist

ReferenceError: Property 'window' doesn't exist
    at gorhom_useAnimatedLayoutTs7 (:1:61)
    at modify (:1:504)
    at reactNativeReanimated_mutablesTs7 (:1:112)
    at apply (native)
    at anonymous (:1:135)
    at forEach (native)
    at reactNativeReanimated_threadsTs5 (:1:102)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions