This error is unusually honest about what is wrong. Xcode found the provisioning profile you asked for, opened it, read the App ID it covers, compared that to the target's bundle identifier, and found they differ. There is no ambiguity and no caching mystery. Two strings are printed and they do not match.
Read them slowly anyway, because the difference is often one character or one suffix at the end of a long reverse-domain string. com.example.app against com.example.app.debug, or a hyphen where the portal has none, is the usual finding.
Which side is wrong
Decide this before you touch anything. Changing the wrong side is how a working App Store build gets a new bundle identifier and turns into a second listing nobody wanted.
- The bundle ID is wrong
- Most common. Someone renamed the target, a build configuration appends a suffix, or an SDK's example bundle identifier survived into the real project. Fix PRODUCT_BUNDLE_IDENTIFIER.
- The profile is wrong
- The target is pinned to a profile from an older identifier, or CI installed a profile from a different app in the same repo. Fix PROVISIONING_PROFILE_SPECIFIER, or the entry in ExportOptions.plist.
- Neither is wrong, the App ID does not exist yet
- The bundle identifier is correct and new, and there is simply no profile for it. Register the App ID and create the profile, then point the target at it.
Read the build settings, not the General tab
The Signing and Capabilities tab shows one bundle identifier. Build settings can produce a different one per configuration, and the build uses the configuration, not the tab. This is the single most common way the two strings diverge without anyone editing them.
# What will this configuration actually build? xcodebuild -showBuildSettings \ -scheme MyApp \ -configuration Release \ | grep -E "PRODUCT_BUNDLE_IDENTIFIER|PROVISIONING_PROFILE_SPECIFIER|DEVELOPMENT_TEAM"
Run it once per configuration. A project that ships fine from Release and fails from Staging is telling you that the Staging configuration appends something, and that the suffixed identifier has no profile of its own.
Read the profile
A .mobileprovision file is a CMS-signed plist. Decode it and print the identifier it covers, so you are comparing facts rather than what the portal's web UI said last week.
PROFILE=~/Library/Developer/Xcode/UserData/Provisioning\ Profiles/abc.mobileprovision security cms -D -i "$PROFILE" > /tmp/p.plist /usr/libexec/PlistBuddy -c 'Print :Name' /tmp/p.plist /usr/libexec/PlistBuddy -c 'Print :Entitlements:application-identifier' /tmp/p.plist
The application-identifier value is printed as team ID, a dot, then the App ID. Ignore the leading team ID when you compare: ABCDE12345.com.example.app and a bundle identifier of com.example.app are a match, not a mismatch. People do change their bundle identifier to include the team prefix after reading this value, and it never ends well.
Fixing it
- 1
Pick the identifier you are actually shipping
For anything already on the App Store, this is settled: it is whatever is in the listing, and it cannot change. Everything else bends around it.
- 2
Set PRODUCT_BUNDLE_IDENTIFIER per configuration
If you want suffixed builds for debug or staging, keep them, but register an App ID and create a profile for each one. A suffix without a matching App ID is not a shortcut, it is this error.
- 3
Name the profile explicitly for each target
Set PROVISIONING_PROFILE_SPECIFIER to the profile name, and list every signed bundle identifier in ExportOptions.plist. Extensions, watch apps, and app clips each have their own identifier and their own profile.
- 4
Clear the stale pin if one exists
Older projects carry a PROVISIONING_PROFILE build setting holding a raw UUID. Xcode no longer writes it and it is easy to miss in the pbxproj. Delete it and use the specifier instead.
xcodebuild archive \ -scheme MyApp \ -archivePath build/MyApp.xcarchive \ CODE_SIGN_STYLE=Manual \ DEVELOPMENT_TEAM=ABCDE12345 \ PRODUCT_BUNDLE_IDENTIFIER=com.example.app \ PROVISIONING_PROFILE_SPECIFIER="MyApp AppStore"
With fastlane match, this error after a rename means the encrypted repo still holds profiles for the old identifier. Running match for the new identifier from a machine with portal permissions creates the missing profile; the readonly CI runs then find it. The old entries are harmless but worth deleting so nobody installs them by accident.
Related messages
- An older wording of the same check reads: Provisioning profile does not match bundle identifier: The provisioning profile specified in your build settings has an AppID which does not match your bundle identifier. Same diagnosis, same fix.
- If the profile cannot be found at all rather than mismatching, you want No profiles for 'com.example.app' were found.
- If the identifier is right but the profile is pinned by UUID, see no such provisioning profile was found.
- Registering the corrected identifier can fail on its own with Failed to register bundle identifier, which means somebody else already owns it.