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
- Create an Expo bare workflow project with RN 0.83.4, Reanimated 4.x, and Worklets 0.8.x
- Add
module:react-native-dotenv to babel.config.js plugins
- Run the app with any Reanimated animation
- 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:
- Remove
['module:react-native-dotenv', ...] from babel.config.js
- Install
react-native-config
- Replace all
import { VAR } from '@env' with:
import Config from 'react-native-config';
// Config.VAR
- 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
Bug Description
module:react-native-dotenvBabel plugin breaks workletization in react-native-reanimated 4.x / react-native-worklets 0.8.x, causing a runtime crash: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
Steps to Reproduce
module:react-native-dotenvtobabel.config.jsplugins[Worklets] Tried to synchronously call a non-worklet function 'addListener' on the UI threadIsolation & Proof
We built an isolated demo app with the exact same RN/Reanimated/Worklets versions:
module:react-native-dotenvin Babel config → ✅ Works perfectly, no crashmodule:react-native-dotenvin Babel config → ❌ Crash immediatelyWe 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:
Workaround / Fix
We migrated from
react-native-dotenvtoreact-native-config:['module:react-native-dotenv', ...]frombabel.config.jsreact-native-configimport { VAR } from '@env'with:react-native-configreads.envat native build time (not via Babel transform), so it does not interfere with the Worklets Babel plugin pipeline.Related Issues