---
title: "Expo Updates"
description: "Automatic context, breadcrumbs, and alerts for Expo OTA updates."
url: https://docs.sentry.io/platforms/react-native/manual-setup/expo/expo-updates/
---

# Expo Updates | Sentry for React Native

When you ship OTA updates with Expo Updates, events captured by Sentry are automatically enriched with information about which update is running. This lets you filter issues by update channel, runtime version, or update ID — and get alerted when an emergency launch occurs.

These integrations are enabled by default in Expo projects. No additional setup is required.

## [Expo Updates Context](https://docs.sentry.io/platforms/react-native/manual-setup/expo/expo-updates.md#expo-updates-context)

Every Sentry event includes an `ota_updates` context with the current update state:

| Field                      | Description                                                 |
| -------------------------- | ----------------------------------------------------------- |
| `update_id`                | UUID of the currently running OTA update                    |
| `channel`                  | Expo Updates channel (for example, `production`, `staging`) |
| `runtime_version`          | Runtime version of the update                               |
| `is_enabled`               | Whether Expo Updates is enabled                             |
| `is_embedded_launch`       | Whether the app launched from the embedded bundle           |
| `is_using_embedded_assets` | Whether the app is using embedded assets                    |
| `is_emergency_launch`      | Whether this was an emergency launch (fallback to embedded) |
| `emergency_launch_reason`  | Reason for the emergency launch (if applicable)             |
| `check_automatically`      | Automatic update check policy                               |
| `launch_duration`          | How long the update launch took (ms)                        |
| `created_at`               | When the update was created                                 |

## [Searchable Tags](https://docs.sentry.io/platforms/react-native/manual-setup/expo/expo-updates.md#searchable-tags)

The SDK also sets the following tags on every event so you can filter and group issues in Sentry:

| Tag                            | Value                      |
| ------------------------------ | -------------------------- |
| `expo.updates.update_id`       | UUID of the running update |
| `expo.updates.channel`         | Update channel name        |
| `expo.updates.runtime_version` | Runtime version string     |

To find all issues from a specific update channel, use `expo.updates.channel:production` in the Sentry issue search.

## [Update Lifecycle Breadcrumbs](https://docs.sentry.io/platforms/react-native/manual-setup/expo/expo-updates.md#update-lifecycle-breadcrumbs)

The SDK automatically records breadcrumbs as the Expo Updates state machine progresses. These breadcrumbs appear on subsequent error events and help you understand what was happening with updates before a crash or error occurred.

All breadcrumbs use the category `expo.updates` and include the following transitions:

| Breadcrumb Message            | Level     | Additional Data |
| ----------------------------- | --------- | --------------- |
| `Checking for update`         | `info`    | —               |
| `Update available`            | `info`    | `updateId`      |
| `Downloading update`          | `info`    | —               |
| `Update downloaded`           | `info`    | `updateId`      |
| `Restarting for update`       | `info`    | —               |
| `Update check failed`         | `error`   | `error`         |
| `Update download failed`      | `error`   | `error`         |
| `Rollback directive received` | `warning` | `commitTime`    |

Update lifecycle breadcrumbs only run in native builds, not in Expo Go.

## [Emergency Launch Warnings](https://docs.sentry.io/platforms/react-native/manual-setup/expo/expo-updates.md#emergency-launch-warnings)

Expo Updates performs an *emergency launch* when it fails to load the latest OTA update and falls back to the embedded bundle. This can silently degrade user experience.

When the SDK detects an emergency launch at startup, it automatically sends a `warning`-level event to Sentry with:

* Message: `Expo Updates emergency launch: <reason>` (or `Expo Updates emergency launch` if no reason is available)
* Tag: `expo.updates.emergency_launch: true`

You can set up a Sentry alert on this tag to get notified whenever an emergency launch happens in production.

Emergency launch detection only runs in native builds, not in Expo Go.

## [Applying Updates](https://docs.sentry.io/platforms/react-native/manual-setup/expo/expo-updates.md#applying-updates)

When your app applies an OTA update at runtime by calling `Updates.reloadAsync()`, the JavaScript bundle is reloaded and `Sentry.init()` runs again. Flush pending events before reloading so anything still queued on the JS side is sent first:

```javascript
import * as Sentry from "@sentry/react-native";
import * as Updates from "expo-updates";

async function applyUpdate() {
  // Send pending events before the JS bundle reloads
  await Sentry.flush();
  await Updates.reloadAsync();
}
```

### [What happens during a reload](https://docs.sentry.io/platforms/react-native/manual-setup/expo/expo-updates.md#what-happens-during-a-reload)

`Updates.reloadAsync()` reloads the JavaScript bundle without restarting the native process. This distinction matters for Sentry:

* **Native SDK**: The native (iOS/Android) SDK is not restarted, so it keeps running across the reload. Native crash handling stays active and the native scope is retained.
* **JavaScript SDK**: The JS runtime restarts, so `Sentry.init()` runs again in the new bundle and the JS-side scope and breadcrumbs start fresh.
* **Active spans**: Performance spans still in progress on the JS side don't survive the runtime restart, so they aren't sent. Finish and flush any span you care about before reloading.
* **Updates context**: After re-initialization, the `ota_updates` context and `expo.updates.*` tags reflect the newly applied update.

### [Recommended update strategy](https://docs.sentry.io/platforms/react-native/manual-setup/expo/expo-updates.md#recommended-update-strategy)

By default, Expo Updates applies a downloaded update on the next app launch (cold start) rather than at runtime. We recommend keeping this default: it lets the SDK initialize cleanly against the new bundle and avoids interrupting active sessions or dropping in-progress spans.

If you apply an update immediately with `Updates.reloadAsync()` (for example, for a critical hotfix), call `Sentry.flush()` first.

## [Expo Constants Context](https://docs.sentry.io/platforms/react-native/manual-setup/expo/expo-updates.md#expo-constants-context)

The SDK automatically captures Expo Constants as an `expo_constants` context on every event. This provides metadata about the execution environment and app configuration:

| Field                   | Description                                                    |
| ----------------------- | -------------------------------------------------------------- |
| `execution_environment` | Where the app is running (`storeClient`, `standalone`, `bare`) |
| `app_ownership`         | Whether the app runs in Expo Go or standalone                  |
| `debug_mode`            | Whether debug mode is enabled                                  |
| `expo_version`          | Expo client version                                            |
| `expo_runtime_version`  | Runtime version from app config                                |
| `session_id`            | Current session ID                                             |
| `status_bar_height`     | Height of the status bar (px)                                  |
| `app_name`              | App name from `app.json`                                       |
| `app_slug`              | App slug from `app.json`                                       |
| `app_version`           | App version from `app.json`                                    |
| `expo_sdk_version`      | Expo SDK version                                               |
| `eas_project_id`        | EAS project ID                                                 |
