Firebase Crashlytics
Upload dSYMs
iOS crashes
Missing dSYMs
App debugging

Firebase Crashlytics Upload missing dSYMs to see crashes from 1 versions.iOS

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If Firebase Crashlytics reports missing dSYMs, the crash stack traces for that iOS build stay partially symbolicated or unreadable. The fix is usually not in Crashlytics itself. It is in your build, archive, or upload pipeline, and the right approach is to make sure the exact symbol files for the shipped binary are produced and uploaded.

What a dSYM Does

A dSYM file maps machine addresses back to function names, source files, and line numbers. When an app crashes in production, Crashlytics receives raw addresses from the compiled binary. Without the matching dSYM, those addresses cannot be translated into a useful call stack.

That is why one version can look healthy while another shows missing symbols. Each archived build can generate a different UUID, so Crashlytics needs the dSYM that belongs to that exact app binary.

Confirm the Build Produced Debug Symbols

Start in Xcode build settings and verify that release builds generate dSYMs.

  • 'Debug Information Format should be DWARF with dSYM File for the relevant configuration.'
  • Archive the app through Xcode or your CI system.
  • Inspect the archive contents instead of assuming the symbols exist.

From a terminal, you can list the dSYM bundles inside an archive:

bash
ARCHIVE_PATH="$HOME/Library/Developer/Xcode/Archives/2026-03-07/MyApp.xcarchive"
find "$ARCHIVE_PATH/dSYMs" -name "*.dSYM" -maxdepth 1

If the archive has no dSYM output, Crashlytics cannot symbolicate that version later.

Upload Symbols with the Crashlytics Script

The Firebase SDK includes an upload-symbols helper. In many projects, the most reliable fix is to upload dSYMs immediately after archiving.

bash
1./Pods/FirebaseCrashlytics/upload-symbols \
2  -gsp path/to/GoogleService-Info.plist \
3  -p ios \
4  path/to/MyApp.app.dSYM

If your project uses Swift Package Manager rather than CocoaPods, the script location differs, but the idea is the same: provide the Google service plist, specify the platform, and point to the dSYM bundle.

In CI, upload all dSYM bundles produced by the archive rather than guessing which one matters.

bash
1find "$ARCHIVE_PATH/dSYMs" -name "*.dSYM" -print0 | while IFS= read -r -d '' file; do
2  ./Pods/FirebaseCrashlytics/upload-symbols \
3    -gsp path/to/GoogleService-Info.plist \
4    -p ios \
5    "$file"
6done

Match the Symbols to the Shipped App

The important detail is not just “upload some dSYMs.” You need the dSYMs from the build that users actually installed. If you rebuild the same source code later, the new archive may not produce matching UUIDs.

You can inspect UUIDs with dwarfdump.

bash
dwarfdump --uuid path/to/MyApp.app.dSYM

Compare that output with the UUID referenced in the Crashlytics missing dSYM alert. If they differ, you are uploading the wrong symbols.

Common Release Pipeline Causes

Several pipeline issues create this problem repeatedly.

Archive Not Preserved

Some CI jobs archive the app, export an IPA, then discard the .xcarchive. That makes it hard to recover the original dSYMs later. Preserve the archive or save the dSYMs as build artifacts.

Upload Step Runs Too Early

If the upload job runs before the archive is complete, it may not find the final dSYM files. Run the symbol upload after the archive step and point it to the archive output, not to a guessed temporary path.

Third-Party Framework Symbols Missing

Your app can crash inside embedded frameworks. If those frameworks produce separate dSYM bundles, upload them too. Crashlytics can only symbolicate what you provide.

A Practical CI Example

A simple release script often looks like this:

bash
1set -euo pipefail
2
3xcodebuild archive \
4  -scheme MyApp \
5  -configuration Release \
6  -archivePath "$ARCHIVE_PATH"
7
8find "$ARCHIVE_PATH/dSYMs" -name "*.dSYM" -print0 | while IFS= read -r -d '' file; do
9  ./Pods/FirebaseCrashlytics/upload-symbols \
10    -gsp ios/MyApp/GoogleService-Info.plist \
11    -p ios \
12    "$file"
13done

That approach is repeatable because the upload consumes the exact symbols from the archived release artifact.

Common Pitfalls

The most common mistake is uploading dSYMs from a rebuild instead of the shipped archive. Another is assuming Debug builds prove the Release pipeline is correct. They do not. Developers also often forget framework dSYMs or point the upload script at the wrong GoogleService-Info.plist. Finally, if symbols are generated correctly but the archive is deleted after export, you lose the only reliable source of matching files.

Summary

  • Crashlytics needs the exact dSYM files that match the released binary.
  • Verify release builds use DWARF with dSYM File.
  • Upload symbols from the .xcarchive, not from a later rebuild.
  • Use dwarfdump --uuid to verify you have the matching symbols.
  • Preserve archives or dSYM artifacts in CI so symbol uploads stay repeatable.

Course illustration
Course illustration

All Rights Reserved.