Skip to content

Crashlytics/upload-symbols picks newest Xcode on the machine, which generates errors for Xcode 27 visible from macOS 26 #16616

Description

@justinseanmartin

Background

I've got an external NVMe drive from which I boot macOS 27 + Xcode 27. On switching back to my macOS 26 boot partition, I started getting 5+ of these errors pop ups and need dismissing during each release builds:

“Xcode-27.0.0-Beta.6” is damaged and can’t be opened. You should move it to the Trash.

The annoying part is it means that it requires user interaction in the GUI to unblock the build process.

This is expected behavior when Xcode 27 is attempted to be launched from macOS 26. However, I was running these builds with Xcode 26.6 selected. I set claude to track down the process that was spawning this Xcode invocation and gatekeeper error modal. This is what it came back with, which seems entirely plausible.

Description

Crashlytics/upload-symbols locates Xcode by asking LaunchServices for every app registered with bundle identifier com.apple.dt.Xcode, then picks the candidate with the highest CoreSymbolicationDT.framework bundle version and dlopens DebugSymbolsDT / CoreSymbolicationDT out of it. It ignores which Xcode is actually selected (xcode-select / the DEVELOPER_DIR that Xcode itself exports into the run-script build phase).

This found the 27 Beta Xcode on the secondary boot volume, which makes upload-symbols load private frameworks from an Xcode that the running OS cannot use.

Reproduction steps

  1. Install two Xcodes where the newer one cannot run on the current OS — e.g. Xcode 26.6 in /Applications and an Xcode 27 beta on another volume (/Volumes/macOS Beta/Applications/Xcode-27.0.0-Beta.6.app), booted into macOS 26.6.2.
  2. sudo xcode-select -s /Applications/Xcode-26.6.0.app/Contents/Developer.
  3. Archive an app whose target has the standard Crashlytics run / upload-symbols --build-phase script phase.

Expected: upload-symbols uses the selected Xcode (DEVELOPER_DIR / xcode-select -p) and uploads dSYMs.

Actual: it loads frameworks from the Xcode 27 beta, Gatekeeper blocks the load with the "damaged" modal, and the build phase blocks until a human dismisses it.

Evidence that upload-symbols is the process holding the beta Xcode open:

$ lsof +D "/Volumes/macOS Beta/Applications/Xcode-27.0.0-Beta.6.app"
COMMAND     PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
upload-sy 21363 jmartin  txt    REG   1,30   776672 38894931 .../Xcode-27.0.0-Beta.6.app/Contents/SharedFrameworks/DebugSymbolsDT.framework/Versions/A/DebugSymbolsDT
upload-sy 21363 jmartin    5r   REG   1,30   776672 38894931 .../Xcode-27.0.0-Beta.6.app/Contents/SharedFrameworks/DebugSymbolsDT.framework/Versions/A/DebugSymbolsDT

$ ps -o pid,ppid,command -p 21363
  PID  PPID COMMAND
21363 21362 .../firebase-ios-sdk/Crashlytics/upload-symbols --build-phase
# 21362 = /bin/sh .../firebase-ios-sdk/Crashlytics/run

The candidate list LaunchServices hands it, in order:

$ mdfind "kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'"
/Volumes/macOS Beta/Users/jmartin/.Trash/Xcode-27.0.0-Beta.5.app
/Volumes/macOS Beta/Applications/Xcode-27.0.0-Beta.6.app
/Applications/Xcode-26.6.0.app                       # <- the selected one

$ xcode-select -p
/Applications/Xcode-26.6.0.app/Contents/Developer

And the versions it compares — the beta wins:

Xcode 27.0b6  CoreSymbolicationDT  CFBundleVersion = 64578.87
Xcode 26.6    CoreSymbolicationDT  CFBundleVersion = 64576.2

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