Skip to content

Babel plugin breaks react-native-worklets/reanimated 4.x workletization (addListener crash) #565

@vladimirivanoviliev

Description

@vladimirivanoviliev

Bug Description

module:react-native-dotenv Babel plugin breaks workletization in react-native-reanimated 4.x / react-native-worklets 0.8.x, causing a runtime crash:

[Worklets] Tried to synchronously call a non-worklet function 'addListener' on the UI thread.

The crash occurs because the dotenv Babel plugin transforms the AST in ways that prevent the Worklets Babel plugin from correctly identifying and marking workletizable functions. This is the same class of Babel transform conflict documented with React Compiler in software-mansion/react-native-reanimated#6826.

Environment

  • React Native: 0.83.4
  • Expo: 55.x (bare workflow)
  • react-native-reanimated: 4.3.0-rc.0
  • react-native-worklets: 0.8.0-rc.0
  • react-native-dotenv: latest
  • Platform: Android (also affects iOS)

Steps to Reproduce

  1. Create an Expo bare workflow project with RN 0.83.4, Reanimated 4.x, and Worklets 0.8.x
  2. Add module:react-native-dotenv to babel.config.js plugins
  3. Run the app with any Reanimated animation
  4. Crash: [Worklets] Tried to synchronously call a non-worklet function 'addListener' on the UI thread

Isolation & Proof

We built an isolated demo app with the exact same RN/Reanimated/Worklets versions:

  • Without module:react-native-dotenv in Babel config → ✅ Works perfectly, no crash
  • With module:react-native-dotenv in Babel config → ❌ Crash immediately

We also tried reordering the plugin (placing dotenv before/after react-native-worklets/plugin) — neither ordering resolves the crash. The Worklets plugin must be listed last per official docs, but dotenv's AST transforms interfere regardless of position.

Root Cause Analysis

The Worklets Babel plugin needs to identify functions that should run on the UI thread and mark them as "worklets." The dotenv plugin's aggressive environment variable inlining transforms the AST before or after workletization, breaking the worklet detection/annotation pipeline.

This is consistent with:

  • React Compiler conflict (reanimated#6826) — same crash pattern, same root cause (Babel transform interference). Reanimated maintainer stated: "it's actually impossible to fix it on our end"
  • expo-router conflict (expo#28933) — dotenv's aggressive inlining breaks expo-router's Babel transforms
  • NativeWind conflict (SO thread) — Babel plugin order conflicts

Workaround / Fix

We migrated from react-native-dotenv to react-native-config:

  1. Remove ['module:react-native-dotenv', ...] from babel.config.js
  2. Install react-native-config
  3. Replace all import { VAR } from '@env' with:
    import Config from 'react-native-config';
    // Config.VAR
  4. Rebuild native apps

react-native-config reads .env at native build time (not via Babel transform), so it does not interfere with the Worklets Babel plugin pipeline.

Related Issues

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