Skip to content

"Upload Debug Symbols to Sentry" build phase causes cycle when project has an embedded app extension #5654

@dapperchris

Description

@dapperchris

What React Native libraries do you use?

Expo Application Services (EAS)

Are you using sentry.io or on-premise?

sentry.io (SaS)

@sentry/react-native SDK Version

7.12.0

How does your development environment look like?

System:
  OS: macOS 26.2
  CPU: (14) arm64 Apple M4 Pro
  Memory: 137.63 MB / 24.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 25.6.0
    path: /opt/homebrew/bin/node
  npm:
    version: 11.8.0
    path: /opt/homebrew/bin/npm
  Watchman:
    version: 2026.01.12.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.16.2
    path: /opt/homebrew/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - iOS 26.2
IDEs:
  Xcode:
    version: 26.2/17C52
    path: /usr/bin/xcodebuild
npmPackages:
  react: 19.1.0
  react-native: 0.81.5
  expo: ~54.0.0
iOS:
  hermesEnabled: true
  newArchEnabled: true

Sentry.init()

Sentry.init({
  dsn: '...',
  environment: 'n-redacted-production',
  tracesSampleRate: 0.2,
  sendDefaultPii: false,
  enableAutoSessionTracking: true,
  attachStacktrace: true,
});

Steps to Reproduce

  1. Create an Expo project with @sentry/react-native/expo in the plugins array
  2. Add an app extension target that gets embedded into the main app — in our case this is a NotificationService extension for Customer.io rich push notifications
  3. Run expo prebuild --clean
  4. Run expo run:ios

The Sentry Expo plugin adds an "Upload Debug Symbols to Sentry" build phase with these inputPaths:

$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Resources/DWARF/$(PRODUCT_NAME)
$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)

...and empty outputPaths. This was added in #5617 to fix a race condition on EAS builds.

The problem is that when the project also embeds an app extension (via a "Copy Files" build phase), Xcode's dependency analysis creates a cycle:

→ Target 'MyApp' has copy command from 'NotificationService.appex' to 'MyApp.app/PlugIns/NotificationService.appex'
○ That command depends on command in Target 'MyApp': script phase "Upload Debug Symbols to Sentry"
○ Target 'MyApp' has a command with output 'MyApp.app.dSYM'
○ Target 'MyApp' has process command with output 'MyApp.app/Info.plist'
○ Target 'MyApp' has copy command from 'NotificationService.appex' to 'MyApp.app/PlugIns/NotificationService.appex'

Essentially: copy extension → Sentry upload phase (ordering) → dSYM generation (inputPaths) → linking → app assembly → copy extension → cycle.

Expected Result

The project builds successfully. The "Upload Debug Symbols to Sentry" build phase should not interfere with Xcode's dependency graph for embedding app extensions.

Actual Result

Build fails with:

error: Cycle inside MyApp; building could produce unreliable results.

Full cycle trace from xcodebuild.log:

Cycle details:
→ Target 'N-REDACTED' has copy command from '.../NotificationService.appex' to '.../N-REDACTED.app/PlugIns/NotificationService.appex'
○ That command depends on command in Target 'N-REDACTED': script phase "Upload Debug Symbols to Sentry"
○ Target 'N-REDACTED' has a command with output '.../N-REDACTED.app.dSYM'
○ Target 'N-REDACTED' has process command with output '.../N-REDACTED.app/Info.plist'
○ Target 'N-REDACTED' has copy command from '.../NotificationService.appex' to '.../N-REDACTED.app/PlugIns/NotificationService.appex'

Metadata

Metadata

Assignees

Projects

Status

Waiting for: Community

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions