After migrating from @clerk/clerk-expo v2.19.25 to @clerk/expo v3.1.5, useSignIn().isLoaded and useSignUp().isLoaded never become true in the iOS Simulator. Auth works perfectly on physical devices (iPhone 17 Pro, iOS 26).
Environment
| Component |
Version |
@clerk/expo |
3.1.5 |
| Expo SDK |
55.0.6 |
| React Native |
0.83.2 |
| React |
19.2.0 |
| Simulator device |
iPhone 16e |
| Simulator iOS |
26.3 |
| Xcode |
26.4 (Build 17E192) |
| macOS |
Darwin 25.4.0 |
| Physical device (works) |
iPhone 17 Pro, iOS 26 |
@clerk/expo is added to the app.json plugins array. Build output confirms: ✅ Clerk iOS plugin loaded.
What we verified
- Network works:
curl from the simulator to the Clerk API (https://<instance>.clerk.accounts.dev/v1/environment) returns the full environment config successfully.
- Publishable key is valid: Test mode key, confirmed via API response.
- Plugin loads: Build output shows
✅ Clerk iOS plugin loaded.
- Physical device works: Same code, same key — auth works perfectly on iPhone 17 Pro.
- Not a timing issue: We polled
isLoaded for 15+ seconds (30 attempts at 500ms). It never becomes true. The client from useClientContext() is permanently null.
- Worked with v2:
@clerk/clerk-expo v2.19.25 worked in the same simulator environment.
Steps to reproduce
- Create an Expo app with
@clerk/expo v3 and add it to app.json plugins
- Build and run in iOS Simulator via
npx expo run:ios
- Navigate to a screen using
useSignIn() or useSignUp()
- Check
isLoaded — it stays false forever
Expected behavior
isLoaded should become true after Clerk initializes, as it does on physical devices.
Additional context
The configureNativeClerk() function in ClerkProvider.js silently swallows errors when the native module fails — the debug logging is compiled out with if (false) guards (lines 92, 130, 153, 162, 168). This makes it extremely hard to diagnose what's going wrong during initialization. Even adding a 15-second polling timeout doesn't help because the client is never populated, not just delayed.
This may be related to previously closed issues #1584 and #3563, but those were closed/locked and this is specific to @clerk/expo v3 on iOS Simulator.
After migrating from
@clerk/clerk-expov2.19.25 to@clerk/expov3.1.5,useSignIn().isLoadedanduseSignUp().isLoadednever becometruein the iOS Simulator. Auth works perfectly on physical devices (iPhone 17 Pro, iOS 26).Environment
@clerk/expo@clerk/expois added to theapp.jsonplugins array. Build output confirms:✅ Clerk iOS plugin loaded.What we verified
curlfrom the simulator to the Clerk API (https://<instance>.clerk.accounts.dev/v1/environment) returns the full environment config successfully.✅ Clerk iOS plugin loaded.isLoadedfor 15+ seconds (30 attempts at 500ms). It never becomestrue. TheclientfromuseClientContext()is permanentlynull.@clerk/clerk-expov2.19.25 worked in the same simulator environment.Steps to reproduce
@clerk/expov3 and add it toapp.jsonpluginsnpx expo run:iosuseSignIn()oruseSignUp()isLoaded— it staysfalseforeverExpected behavior
isLoadedshould becometrueafter Clerk initializes, as it does on physical devices.Additional context
The
configureNativeClerk()function inClerkProvider.jssilently swallows errors when the native module fails — the debug logging is compiled out withif (false)guards (lines 92, 130, 153, 162, 168). This makes it extremely hard to diagnose what's going wrong during initialization. Even adding a 15-second polling timeout doesn't help because theclientis never populated, not just delayed.This may be related to previously closed issues #1584 and #3563, but those were closed/locked and this is specific to
@clerk/expov3 on iOS Simulator.