Skip to content

🔥 [iOS][SPM][Crashlytics] dSYM upload-symbols script hardcodes ${PROJECT_DIR}/GoogleService-Info.plist, ignoring Expo/target-folder location #9304

Description

@joelwillSeek

Issue

@react-native-firebase/crashlytics's iOS build-phase script (ios_config.sh) hardcodes the path to GoogleService-Info.plist as ${PROJECT_DIR}/GoogleService-Info.plist when uploading dSYMs via the SPM upload-symbols binary. This assumes the plist lives directly next to the .xcodeproj, but the standard/Expo-generated location for the plist is inside the app target's own source folder (${PROJECT_DIR}/<TargetName>/GoogleService-Info.plist), which is also where @react-native-firebase/app's own Expo config plugin (googleServicesPlist.ts) copies it to.

The result is a build-time error even though the plist exists, is correctly referenced in app.json, and is correctly linked into the Xcode project as a resource:

The file is actually present one directory deeper, at ios/<TargetName>/GoogleService-Info.plist.

Relevant script (from packages/crashlytics/ios_config.sh):

else

SPM: upload-symbols is at a known path in the SourcePackages checkout.

SPM_CRASHLYTICS_DIR="${BUILD_DIR%Build/*}SourcePackages/checkouts/firebase-ios-sdk/Crashlytics"
SPM_UPLOAD_SYMBOLS="${SPM_CRASHLYTICS_DIR}/upload-symbols"
if [[ -x "${SPM_UPLOAD_SYMBOLS}" ]]; then
"${SPM_UPLOAD_SYMBOLS}" -gsp "${PROJECT_DIR}/GoogleService-Info.plist" -p ios "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"

This else branch (the SPM path) is new in v26 — it doesn't exist in v25.1.0's ios_config.sh, which only has the CocoaPods (${PODS_ROOT}/FirebaseCrashlytics/run) and legacy-framework (${PROJECT_DIR}/FirebaseCrashlytics.framework/run) branches, neither of which reference GoogleService-Info.plist directly — the CocoaPods run tool resolves it from inside the Pods sandbox itself.

Since v26 made SPM the default resolution mechanism for the Firebase Apple SDK, every SPM-based Crashlytics setup with the plist in the standard target-folder location (which is what @react-native-firebase/app's own plugin produces under Expo) will hit this.

Suggested fix: fall back to ${PROJECT_DIR}/${TARGET_NAME}/GoogleService-Info.plist (or search both locations) before failing, the same way the plist is resolved for the main app bundle.

Project Files
Javascript
package.json (relevant deps):

{
"expo": "~55.0.28",
"react-native": "0.83.10",
"react": "19.2.0",
"@react-native-firebase/app": "^26.4.0",
"@react-native-firebase/analytics": "^26.4.0",
"@react-native-firebase/crashlytics": "^26.4.0",
"expo-build-properties": "~55.0.16"
}
app.json (relevant plugin config):

[
"expo-build-properties",
{
"ios": {
"useFrameworks": "dynamic"
}
}
],
"@react-native-firebase/app",
"@react-native-firebase/crashlytics"
expo.ios.googleServicesFile: "./GoogleService-Info.plist" — file exists at repo root, is committed to git, and its BUNDLE_ID matches expo.ios.bundleIdentifier exactly.

iOS
Managed Expo project (Continuous Native Generation) — no manually maintained Podfile; native ios/ project generated via expo prebuild. GoogleService-Info.plist is correctly copied by @react-native-firebase/app's own config plugin to ios//GoogleService-Info.plist, confirmed present on disk at build time.

Environment
react-native info output:

PASTE YOUR npx react-native info OUTPUT HERE
Platform that you're experiencing the issue on:
iOS
react-native-firebase version you're using that has this issue:
26.4.0
Firebase module(s) you're using that has the issue:
Crashlytics (dSYM upload build phase)
Are you using TypeScript?
Y & 5.9.2
Using Expo managed workflow (SDK 55), New Architecture enabled (newArchEnabled=true)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions