---
title: Symbolicating crash reports with dSYMs
description: Upload dSYM files to Honeybadger to get readable stack traces from iOS, macOS, and visionOS crash reports.
url: https://docs.honeybadger.io/lib/cocoa/errors/using-dsyms/
---

When Xcode builds your app for distribution, it strips debug symbols from the binary to reduce file size. These symbols are saved separately in a `.dSYM` bundle alongside your build. Without uploading these bundles to Honeybadger, crash reports will show raw memory addresses instead of the function names, file names, and line numbers you need to diagnose the crash.

Uploading dSYMs lets Honeybadger display fully symbolicated stack traces like:

```plaintext
triggerExceptionCrash()   ViewController.swift:42
AppDelegate.application   AppDelegate.swift:18
```

No SDK configuration is needed for symbolication: every crash report already includes the metadata of each binary image loaded in the crashed process (its build UUID, load address, and architecture). Honeybadger matches this data to your uploaded dSYMs by build UUID, so all you need to do is upload the dSYMs for each build you distribute.

## Uploading with the upload script

The Honeybadger SDK ships with an upload script, `bin/upload-dsyms.sh`, which uploads all `.dSYM` bundles for a build to Honeybadger. It automatically reads `DWARF_DSYM_FOLDER_PATH` (which Xcode sets during a build), so no extra configuration is needed when run from a build phase. Store your API key in an Xcode build setting or environment variable rather than hardcoding it.

### Xcode build phase (recommended)

Add the script as a Run Script build phase so dSYMs upload automatically whenever you archive a build:

1. In Xcode, select your app target and go to **Build Phases**.
2. Click **+** and select **New Run Script Phase**.
3. Drag the new phase to the **end** of the list, after **Link Binary With Libraries**, so it runs after Xcode has produced the dSYM for the build.
4. Add the run script for your installation method (below).

**CocoaPods** — the script is installed with the pod, so reference it from `${PODS_ROOT}`:

```shell
bash "${PODS_ROOT}/Honeybadger/bin/upload-dsyms.sh" --api-key "${HB_API_KEY}" --warn-only
```

**Swift Package Manager** — SPM does not install standalone scripts to a referenceable location. Download [`bin/upload-dsyms.sh`](https://github.com/honeybadger-io/honeybadger-cocoa/blob/main/bin/upload-dsyms.sh) from the SDK repository, add it to your project (e.g. at `Scripts/upload-dsyms.sh`), and reference it:

```shell
bash "${SRCROOT}/Scripts/upload-dsyms.sh" --api-key "${HB_API_KEY}" --warn-only
```

`--warn-only` makes the script exit 0 when one or more uploads fail (for example, on a transient network error), so a failed upload never fails your archive. Setup problems, such as a missing API key or a missing `curl`, `zip`, or `python3`, still exit nonzero so they aren’t hidden. Omit `--warn-only` in CI, where a nonzero exit on failed uploads is what you want.

### Manual / CI upload

To upload dSYMs manually or from a CI pipeline, run the script directly and pass the dSYM directory with `--dsym-path`:

```shell
bash /path/to/upload-dsyms.sh --api-key PROJECT_API_KEY --dsym-path /path/to/dSYMs/
```

The script uploads all `.dSYM` bundles found in the specified directory.

## Uploading to the EU stack

If your Honeybadger account is in our [EU region](https://docs.honeybadger.io/resources/data-residency/), pass the EU endpoint with `--endpoint` wherever you run the script:

```shell
bash /path/to/upload-dsyms.sh --api-key PROJECT_API_KEY --endpoint "https://eu-api.honeybadger.io"
```

The endpoint is the base URL of the Honeybadger API, so `--endpoint` also works for routing uploads through a proxy. Note that this only affects dSYM uploads; the SDK’s error-reporting endpoint is [configured separately](https://docs.honeybadger.io/lib/cocoa/#initialization).

## Versioning your project (optional)

If you configure a **revision** in the SDK (the `revision:` parameter of [`configure`](https://docs.honeybadger.io/lib/cocoa/#initialization)), pass the **same value** to the upload script with `--revision`, so the uploaded dSYMs and the errors they symbolicate are tagged with the same release:

```shell
bash /path/to/upload-dsyms.sh --api-key PROJECT_API_KEY --revision "1.4.2"
```

Unlike source maps for JavaScript, dSYM-to-crash matching does not depend on the revision — it’s done by build UUID, so symbolication works with or without one. Revision is purely for release tracking.

---

## Try Honeybadger for FREE

Intelligent logging, error tracking, and Just Enough APM™ in one dev-friendly platform. Find and fix problems before users notice.

[Start free trial](https://app.honeybadger.io/users/sign_up)

[See plans and pricing](https://www.honeybadger.io/plans/)
