Skip to content

[iOS] Expo SDK 57 / RN 0.86: envelopes reported sent (HTTP 200) but never ingested; works on SDK 56 #6630

Description

@toshoyeb

What React Native libraries do you use?

Hermes, RN New Architecture, Expo Application Services (EAS), Expo (mobile only), Expo Router, React Navigation

Are you using sentry.io or on-premise?

sentry.io (SaS)

Are you using any other error monitoring solution alongside Sentry?

Yes

Other Error Monitoring Solution Name

Firebase Crashlytics (@react-native-firebase/crashlytics), native crash capture only

@sentry/react-native SDK Version

8.17.2 — also reproduced on 8.24.0. The SDK version is not the variable; see below.

How does your development environment look like?

macOS 26.2 (arm64), Xcode 26.6, node v22.19.0, npm 11.7.0
Device: iPhone12,1 (iPhone 11), iOS 26.6 — physical device, not simulator

BROKEN                              WORKING
expo               57.0.17          expo               56.0.21
react-native       0.86.3           react-native       0.85.3
expo-router        57.0.17          expo-router        56.2.20
expo-updates       57.0.18          expo-updates       56.0.26
reanimated         4.5.4            reanimated         4.5.4      (identical)
worklets           0.10.4           worklets           0.10.4     (identical)
@sentry/react-native 8.17.2         @sentry/react-native 8.17.2   (identical)

expo-build-properties, iOS section (unchanged across both):

ios: {
  useFrameworks: 'static',          // required by @react-native-firebase
  buildReactNativeFromSource: true,
}

Sentry.init()

import * as Sentry from '@sentry/react-native';

const reactNavigationIntegration = Sentry.reactNavigationIntegration();

Sentry.init({
  dsn: 'https://<key>@o<org>.ingest.us.sentry.io/<project>',
  environment: 'development',
  dist: Updates.updateId ?? undefined,
  sendDefaultPii: true,
  enableLogs: true,
  tracesSampleRate: 1.0,
  integrations: (integrations) => [
    ...integrations.filter((i) => i.name !== 'ConsoleLogs'),
    reactNavigationIntegration,
  ],
});

export default Sentry.wrap(function RootLayout() { /* ... */ });

Steps to Reproduce

  1. Expo app on SDK 56 (RN 0.85.3) with @sentry/react-native@8.17.2, enableLogs: true,
    tracesSampleRate: 1.0, and expo-build-properties iOS
    { useFrameworks: 'static', buildReactNativeFromSource: true }.
  2. Build an iOS development client via EAS (developmentClient: true, internal
    distribution), run on a physical device. Confirm logs and spans arrive in Sentry.
  3. Upgrade only the Expo SDK to 57 (RN 0.86.3): expo, expo-router, expo-updates
    and the other Expo-managed packages. Leave @sentry/react-native at 8.17.2 and leave
    react-native-reanimated / react-native-worklets unchanged.
  4. rm -rf ios, rebuild the same EAS iOS development profile, run on the same device,
    same DSN, same network.
  5. Exercise the app so it emits Sentry.logger.info(...) and HTTP spans.

Android built from the same commit is unaffected throughout. Downgrading back to SDK 56
restores delivery immediately, on the same device and DSN.

Expected Result

iOS logs and spans appear in Sentry, as they do on SDK 56 and as they do on Android from
the identical commit.

Actual Result

Nothing from the iOS build reaches Sentry — no logs, no spans, no transactions.
Android from the same commit is fine. The device believes it succeeded.

With debug: true, sentry-cocoa reports a successful send:

[Native] [SentrySerializationSwift] Header {"sdk":{"name":"sentry.javascript.react-native","version":"8.17.2"}}
[Native] [SentrySerializationSwift] Item Header {"type":"log","item_count":2,"content_type":"application/vnd.sentry.items.log+json","length":1982}
[Native] [Sentry] Constructed request: SentryURLRequestFactory
[Native] [SentryRequestOperation] Request status: 200
[Native] [SentryRequestOperation] Request response: {}
[Native] [SentryHttpTransport] Received response status code: 200
[Native] [SentryHttpTransport] Deleting envelope and sending next.
[Native] [SentryHttpTransport] No envelopes left to send.

A transaction envelope in the same session returned an event id:

[Native] [SentryRequestOperation] Request response: {"id":"da4411d903794e09a2e2330922198bcf"}

That event id is not retrievable: GET /api/0/projects/<org>/<project>/events/da4411.../
returns 404 Event not found, and it does not appear in the ourlogs, spans or errors
datasets.

Sentry's outcomes ledger has no record of it either — the data is counted as neither
accepted nor discarded. Over a 3-day window, stats_v2 grouped by outcome and reason:

log_item      accepted 26476   invalid/timestamp 6    client_discard/send_error 51
span          accepted 10887   invalid_transaction 42
transaction   accepted  7248   invalid_transaction  2

All of the accepted volume is Android plus older iOS binaries. Querying the Logs dataset
by platform over 48h during the failure:

Android  staging       6515
iOS      production    2821   <- older App Store builds, pre-upgrade
Android  production    1241
Android  development    500
iOS      development      0   <- the SDK 57 build
iOS      staging          0   <- the SDK 57 build

What was ruled out

  • SDK version — reproduced identically on 8.17.2 and 8.24.0.
  • Project configuration — no inbound filters, no rate limit, single active DSN key,
    quota healthy, allowedDomains: ["*"].
  • Logs specifically — spans and transactions are missing too, so it is not the Logs
    product.
  • Device / network / account — the pre-upgrade iOS binary logs fine from the same
    device, same DSN, same Wi-Fi, at the same time.
  • reanimated / worklets — held at 4.5.4 / 0.10.4 across both trees.

Workaround

enableNative: false restores delivery completely on the SDK 57 build. That makes
makeNativeTransportFactory return null so the JS client falls back to
makeFetchTransport and posts envelopes itself, bypassing sentry-cocoa. This localises the
failure to the native transport path on iOS under Expo SDK 57 / RN 0.86.

Note the side effect: logEnricherIntegration is only installed when enableNative is
true (integrations/default.js), so with the workaround every log row loses os.name,
os.version, device.* and sentry.release and becomes unfilterable by platform. We
restore those with Sentry.setAttributes() on the isolation scope.

Possibly related

Both describe the same shape — processed locally, never delivered, iOS, after an Expo SDK
upgrade — and neither has a resolution.

Metadata

Metadata

Assignees

Projects

Status
No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions