Skip to content

Troubleshooting

By design, Expo’s OTA system is fail-silent. If something goes wrong, the app will simply continue using its current JavaScript bundle instead of crashing.

To diagnose why an update isn’t being applied, follow these steps:

This is a successful response, but it means the server has decided not to serve an update.

  • Diagnosing Runtime Mismatches: Ensure the runtimeVersion in your app.json matches exactly with the update you published.
  • Checking Current Update ID: If the device already has the latest update, the server will return 204. Check the expo-current-update-id header sent by the device.

This typically indicates that the metadata exists in D1, but the physical assets are missing from storage.

  • Asset Sync Issues: Verify that the dist/_expo and dist/assets folders were successfully uploaded to the R2 bucket.
  • Checking Proxy Routes: Ensure the Hono worker’s /_expo/* and /assets/* routes are correctly configured to proxy to your R2 bucket.

If you’ve enabled code signing, the app will reject any manifest that doesn’t have a valid signature.

  • Native Logs: Use adb logcat -s ExpoUpdates (Android) or the iOS Console to look for Signature validation failed errors.

You can simulate a device check from your terminal:

Terminal window
curl -v -H "expo-platform: ios"
-H "expo-runtime-version: 1.0.0"
-H "expo-channel-name: production"
-H "expo-protocol-version: 1"
https://your-worker-subdomain.workers.dev/update
  • Android: adb logcat -s ExpoUpdates
  • iOS: Open Console.app, select your device, and filter by ExpoUpdates.
  • Expo Go: Note that custom OTA servers often behave differently in Expo Go. We recommend testing with Development Builds.