getsentry / sentry-react-native

Official Sentry SDK for React Native
https://sentry.io
MIT License
1.57k stars 337 forks source link

Using `expo-datadog` and `@sentry/react-native/expo` in Expo results in missing bundle file #3941

Open lepskiy opened 3 months ago

lepskiy commented 3 months ago

OS:

Platform:

SDK:

SDK version: 5.20.0

react-native version: 0.73.6

Are you using Expo?

Are you using sentry.io or on-premise?

Configuration:

(@sentry/react-native)

const init = () => {
  Sentry.init({
    dsn: SENTRY_DSN,
    debug: false,
    enableNative: !__DEV__,
    integrations: [new Sentry.ReactNativeTracing({ routingInstrumentation })],
  });
};

I have the following issue:

After upgrading to Expo 50 and migrating from sentry-expo to @sentry/react-native the build (using remote EAS Build) started failing.

Steps to reproduce: 1) Migrate to from sentry-expo to @sentry/react-native using the link https://github.com/expo/fyi/blob/main/sentry-expo-migration.md 2) Run build: eas build --profile devclient --platform ios

Actual result:

EAS build is failed with the error:

› Executing MobileAppX » Bundle React Native code and images
⚠️  Script has ambiguous dependencies causing it to run on every build.
   To fix, go to: Xcode » MobileAppX/MobileAppX » Build Phases » 'Upload Debug Symbols to Sentry'
   Either: Uncheck "Based on dependency analysis", or select output files to trigger the script
⚠️  Script has ambiguous dependencies causing it to run on every build.
   To fix, go to: Xcode » MobileAppX/MobileAppX » Build Phases » 'Upload dSYMs to Datadog'
   Either: Uncheck "Based on dependency analysis", or select output files to trigger the script
⚠️  Script has ambiguous dependencies causing it to run on every build.
   To fix, go to: Xcode » MobileAppX/MobileAppX » Build Phases » '[CP-User] [RNFB] Core Configuration'
   Either: Uncheck "Based on dependency analysis", or select output files to trigger the script
⚠️  Script has ambiguous dependencies causing it to run on every build.
   To fix, go to: Xcode » MobileAppX/MobileAppX » Build Phases » '[CP-User] [RNFB] Crashlytics Configuration'
   Either: Uncheck "Based on dependency analysis", or select output files to trigger the script
▸ ** BUILD FAILED **
▸ The following build commands failed:
▸   PhaseScriptExecution Bundle\ React\ Native\ code\ and\ images /Users/expo/workingdir/build/ios/build/Build/Intermediates.noindex/MobileAppX.build/Debug-iphonesimulator/MobileAppX.build/Script-00DD1BFF1BD5951E006B06BC.sh (in target 'MobileAppX' from project 'MobileAppX')
▸ (1 failure)
** BUILD FAILED **
The following build commands failed:
    PhaseScriptExecution Bundle\ React\ Native\ code\ and\ images /Users/expo/workingdir/build/ios/build/Build/Intermediates.noindex/MobileAppX.build/Debug-iphonesimulator/MobileAppX.build/Script-00DD1BFF1BD5951E006B06BC.sh (in target 'MobileAppX' from project 'MobileAppX')
(1 failure)

Exit status: 65

XCode logs:

    /bin/sh -c /Users/expo/workingdir/build/ios/build/Build/Intermediates.noindex/MobileAppX.build/Debug-iphonesimulator/MobileAppX.build/Script-00DD1BFF1BD5951E006B06BC.sh
+ LOCAL_NODE_BINARY=/Users/expo/.nvm/versions/node/v20.13.1/bin/node
+ '[' -z '' ']'
+ export SENTRY_PROPERTIES=sentry.properties
+ SENTRY_PROPERTIES=sentry.properties
+ '[' -z '' ']'
+ export SOURCEMAP_FILE=/Users/expo/workingdir/build/ios/build/Build/Intermediates.noindex/MobileAppX.build/Debug-iphonesimulator/MobileAppX.build/DerivedSources/main.jsbundle.map
+ SOURCEMAP_FILE=/Users/expo/workingdir/build/ios/build/Build/Intermediates.noindex/MobileAppX.build/Debug-iphonesimulator/MobileAppX.build/DerivedSources/main.jsbundle.map
+ '[' -z '' ']'
++ /Users/expo/.nvm/versions/node/v20.13.1/bin/node --print 'require('\''path'\'').dirname(require.resolve('\''@sentry/cli/package.json'\''))'
+ SENTRY_CLI_PACKAGE_PATH=/Users/expo/workingdir/build/node_modules/@sentry/cli
+ '[' -z '' ']'
+ SENTRY_CLI_EXECUTABLE=/Users/expo/workingdir/build/node_modules/@sentry/cli/bin/sentry-cli
+ REACT_NATIVE_XCODE=/Users/expo/workingdir/build/node_modules/react-native/scripts/react-native-xcode.sh
+ [[ '' == false ]]
+ ARGS=' --force-foreground --log-level=debug '
+ REACT_NATIVE_XCODE_WITH_SENTRY='"/Users/expo/workingdir/build/node_modules/@sentry/cli/bin/sentry-cli" react-native xcode  --force-foreground --log-level=debug  "/Users/expo/workingdir/build/node_modules/react-native/scripts/react-native-xcode.sh"'
+ '[' '' '!=' true ']'
+ /bin/sh -c '"/Users/expo/.nvm/versions/node/v20.13.1/bin/node" "/Users/expo/workingdir/build/node_modules/@sentry/cli/bin/sentry-cli" react-native xcode  --force-foreground --log-level=debug  "/Users/expo/workingdir/build/node_modules/react-native/scripts/react-native-xcode.sh"'
  INFO    2024-07-11 05:55:36.678262 -07:00 Loaded file referenced by SENTRY_PROPERTIES (sentry.properties)
  DEBUG   2024-07-11 05:55:36.701518 -07:00 sentry-cli version: 2.30.0, platform: "darwin", architecture: "arm64"
  INFO    2024-07-11 05:55:36.701557 -07:00 sentry-cli was invoked with the following command line: "/Users/expo/workingdir/build/node_modules/@sentry/cli-darwin/bin/sentry-cli" "react-native" "xcode" "--force-foreground" "--log-level=debug" "/Users/expo/workingdir/build/node_modules/react-native/scripts/react-native-xcode.sh"
  INFO    2024-07-11 05:55:36.701651 -07:00 Issuing a command for Organization: mpileappx Project: mpileappx
  INFO    2024-07-11 05:55:36.701658 -07:00 Using react-native build script at /Users/expo/workingdir/build/ios
  INFO    2024-07-11 05:55:36.701661 -07:00 Running in debug mode, skipping script wrapping.
+ DEST=/Users/expo/workingdir/build/ios/build/Build/Products/Debug-iphonesimulator/MobileAppX.app
+ [[ ! -n '' ]]
+ [[ Debug = *Debug* ]]
+ [[ ! iphonesimulator == *simulator ]]
+ [[ -n 1 ]]
+ echo 'SKIP_BUNDLING enabled; skipping.'
SKIP_BUNDLING enabled; skipping.
+ exit 0
+ '[' -z '' ']'
++ /Users/expo/.nvm/versions/node/v20.13.1/bin/node --print 'require('\''path'\'').dirname(require.resolve('\''@sentry/react-native/package.json'\''))'
+ SENTRY_RN_PACKAGE_PATH=/Users/expo/workingdir/build/node_modules/@sentry/react-native
+ '[' -z '' ']'
+ SENTRY_COLLECT_MODULES=/Users/expo/workingdir/build/node_modules/@sentry/react-native/scripts/collect-modules.sh
+ '[' -f /Users/expo/workingdir/build/node_modules/@sentry/react-native/scripts/collect-modules.sh ']'
+ /bin/sh /Users/expo/workingdir/build/node_modules/@sentry/react-native/scripts/collect-modules.sh
+ [[ Debug = *Debug* ]]
+ echo 'Debug build. Modules are not collected.'
Debug build. Modules are not collected.
+ exit 0
No sourcemap output has been specified.
Check that you either set a SOURCEMAP_FILE or an EXTRA_PACKAGER_ARGS environment variable in your "Bundle React Native code and images" Build Phase in XCode.
If you are not running this script from XCode, set a SOURCEMAP_FILE environment variable before running the script.
Command PhaseScriptExecution failed with a nonzero exit code

Expected result:

Build finish succesfully.

kahest commented 3 months ago

Hey @lepskiy thanks for reporting, we'll take a look. Note that due to conference and PTOs we might be a bit slower to respond than usual.

Also, can you confirm that this is the same issue as you reported in https://github.com/getsentry/sentry-react-native/issues/3551#issuecomment-2223310019?

kahest commented 3 months ago

Please also refer to our migration guide from sentry-expo to @sentry/react-native: https://docs.sentry.io/platforms/react-native/migration/sentry-expo/

lepskiy commented 3 months ago

Hey @lepskiy thanks for reporting, we'll take a look. Note that due to conference and PTOs we might be a bit slower to respond than usual.

Also, can you confirm that this is the same issue as you reported in #3551 (comment)?

Confirm, this is a duplicate. I've just decided to create a new ticket instead of the comment in the closed one.

krystofwoldrich commented 3 months ago

Hi @lepskiy, the message at the end of the build log is from a DataDog script which is causing the build to fail.

The message

No sourcemap output has been specified.
Check that you either set a SOURCEMAP_FILE or an EXTRA_PACKAGER_ARGS environment variable in your "Bundle React Native code and images" Build Phase in XCode.
If you are not running this script from XCode, set a SOURCEMAP_FILE environment variable before running the script.
Command PhaseScriptExecution failed with a nonzero exit code

The log you shared is from a Debug build. Sentry doesn't look for a source maps in debug builds as no bundles are generated.

The Sentry log from above:

  INFO    2024-07-11 05:55:36.701661 -07:00 Running in debug mode, skipping script wrapping.
jhbarnett commented 2 months ago

Had the same EAS build error with both expo-datadog and @sentry/react-native/expo included in our config plugins. After moving datadog below sentry in the list of plugins our builds succeed. But then the app crashes on open.

Alternatively, when either one of the config plugins is excluded, the app builds and runs successfully.

Tested with @sentry/react-native versions 5.22, 5.25, and 5.26 and expo-datadog 51.0.

Crash report indicates an uncaught exception throwing RCTFatal in RCTCxxBridge. Logs state: "No bundle URL present. Make sure you're running a packager server or have included a .jsbundle file in your application bundle."

lepskiy commented 2 months ago

Had the same EAS build error with both expo-datadog and @sentry/react-native/expo included in our config plugins. After moving datadog below sentry in the list of plugins our builds succeed. But then the app crashes on open.

Alternatively, when either one of the config plugins is excluded, the app builds and runs successfully.

Tested with @sentry/react-native versions 5.22, 5.25, and 5.26 and expo-datadog 51.0.

Crash report indicates an uncaught exception throwing RCTFatal in RCTCxxBridge. Logs state: "No bundle URL present. Make sure you're running a packager server or have included a .jsbundle file in your application bundle."

Completely the same. After moving DataDog below Sentry the build is fixed but the build is crashed on iOS (on Android works fine).

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Termination Reason: SIGNAL 6 Abort trap: 6
Terminating Process: MobileAppX [8373]

Triggered by Thread:  0

Application Specific Information:
abort() called

Last Exception Backtrace:
0   CoreFoundation                         0x197738f20 __exceptionPreprocess + 164
1   libobjc.A.dylib                        0x18f5e6018 objc_exception_throw + 60
2   MobileAppX                             0x10508e67c 0x104b90000 + 5236348
3   MobileAppX                             0x1050a619c 0x104b90000 + 5333404
4   libdispatch.dylib                      0x19f5dc13c _dispatch_call_block_and_release + 32
5   libdispatch.dylib                      0x19f5dddd4 _dispatch_client_callout + 20
6   libdispatch.dylib                      0x19f5ec5a4 _dispatch_main_queue_drain + 988
7   libdispatch.dylib                      0x19f5ec1b8 _dispatch_main_queue_callback_4CF + 44
8   CoreFoundation                         0x19770b710 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
9   CoreFoundation                         0x197708914 __CFRunLoopRun + 1996
10  CoreFoundation                         0x197707cd8 CFRunLoopRunSpecific + 608
11  GraphicsServices                       0x1dc5b81a8 GSEventRunModal + 164
12  UIKitCore                              0x199d4090c -[UIApplication _run] + 888
13  UIKitCore                              0x199df49d0 UIApplicationMain + 340
14  MobileAppX                             0x104b98418 0x104b90000 + 33816
15  dyld                                   0x1badb9e4c start + 2240

Thread 0 name:   Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib                 0x1e07f342c __pthread_kill + 8
1   libsystem_pthread.dylib                0x1f4592c0c pthread_kill + 268
2   libsystem_c.dylib                      0x19f696c34 __abort + 136
3   libsystem_c.dylib                      0x19f696bac abort + 192
4   libc++abi.dylib                        0x1f44b0ca4 abort_message + 132
5   libc++abi.dylib                        0x1f44a0e5c demangling_terminate_handler() + 348
6   libobjc.A.dylib                        0x18f601e2c _objc_terminate() + 144
7   MobileAppX                             0x104f709b8 0x104b90000 + 4065720
8   libc++abi.dylib                        0x1f44b0068 std::__terminate(void (*)()) + 16
9   libc++abi.dylib                        0x1f44b000c std::terminate() + 108
10  libdispatch.dylib                      0x19f5ddde8 _dispatch_client_callout + 40
11  libdispatch.dylib                      0x19f5ec5a4 _dispatch_main_queue_drain + 988
12  libdispatch.dylib                      0x19f5ec1b8 _dispatch_main_queue_callback_4CF + 44
13  CoreFoundation                         0x19770b710 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
14  CoreFoundation                         0x197708914 __CFRunLoopRun + 1996
15  CoreFoundation                         0x197707cd8 CFRunLoopRunSpecific + 608
16  GraphicsServices                       0x1dc5b81a8 GSEventRunModal + 164
17  UIKitCore                              0x199d4090c -[UIApplication _run] + 888
18  UIKitCore                              0x199df49d0 UIApplicationMain + 340
19  MobileAppX                             0x104b98418 0x104b90000 + 33816
20  dyld                                   0x1badb9e4c start + 2240
krystofwoldrich commented 2 months ago

Hi @lepskiy and @jhbarnett, thank you for the details.

The conclusion is using expo-datadog and @sentry/react-native/expo will cause the bundle file missing in the application bundle. Depending on the order the build crashes or the app crashes on start due to the missing bundle.

krystofwoldrich commented 2 months ago

Would you be able to provide a reproducible example?

krystofwoldrich commented 2 months ago

Small note, I see that the shared Bundle React Native and image build phase looks outdated.

Could you regenerate the native projects or update the build phase manually to use sentry-xcode.sh https://docs.sentry.io/platforms/react-native/manual-setup/manual-setup/#configure-automatic-source-maps-upload?

krystofwoldrich commented 2 months ago

How to use expo-datadog and @sentry/react-native in one project?

⚠️ Warning: We do not recommend using multiple monitoring and crash reporting SDKs at once as it might result in unexpected behaviour. Always test your application and check that you are receiving correct data from all the SDKs in use.

Both expo-datadog and @sentry/react-native/plugin Expo plugins ensure automatic upload of debug files (source maps and native symbols) to the respective platforms. To do so these plugins change the content of the Bundle React Native code and images build phase in the app Xcode project.

When both plugins are used the build phase results in valid bash script, but the executed commands will fail to produce the JS Bundle.

Recommendation 1: Use only one of the plugins. If you are using only of the SDKs to capture errors, use its plugin. The other SDK if not used for errors doesn't need the auto debug files upload.

Recommendation 2: Use none of the plugins and upload the debug files manually. To see how to generate and upload source maps you can follow this guide https://docs.sentry.io/platforms/react-native/sourcemaps/uploading/expo-advanced/#manual-upload-for-hermes-release

⚠️ Unstable Recommendation 3: Use the plugin in the following order @sentry/react-native/plugin first then expo-datadog. This currently aligns with expo-datadog, @sentry/react-native order in the app.json, but might change any time. And add export SOURCEMAP_FILE=$DERIVED_FILE_DIR/main.jsbundle.map to your envs, for example by using ios/.xcode.env

krystofwoldrich commented 2 months ago

Remarks:

Execution order expo-datadog, @sentry/react-native/expo results in:

export SOURCEMAP_FILE=$DERIVED_FILE_DIR/main.jsbundle.map

if [[ -z "$DATADOG_CI_EXEC" ]]; then
    DATADOG_CI_EXEC="$("$NODE_BINARY" --print "require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')")";

    # Check if the file exists and is executable
    if [[ -x "$DATADOG_CI_EXEC" ]]; then
        export DATADOG_CI_EXEC;
    else
        echo "Error: DATADOG_CI_EXEC does not exist or is not executable";
        exit 1;
    fi
fi

/bin/sh `"$NODE_BINARY" --print "require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode.sh'"` $DATADOG_CI_EXEC react-native xcode `"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"`

The issue is sentry-xcode.sh takes only one arg. But in this case receives multiple.


Execution order @sentry/react-native/expo, expo-datadog results in:

/bin/sh `"$NODE_BINARY" --print "require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode.sh'"` `"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"`

if [[ -z "$DATADOG_CI_EXEC" ]]; then
    DATADOG_CI_EXEC="$("$NODE_BINARY" --print "require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')")";

    # Check if the file exists and is executable
    if [[ -x "$DATADOG_CI_EXEC" ]]; then
        export DATADOG_CI_EXEC;
    else
        echo "Error: DATADOG_CI_EXEC does not exist or is not executable";
        exit 1;
    fi
fi

$DATADOG_CI_EXEC react-native xcode `"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"`

In this case SOURCEMAP_FILE env is missing and that why the DD CLI fails. This will also run the bundle creating twice.