iOS · build & submit

Provisioning profile doesn't include signing certificate

Provisioning profile "X" doesn't include signing certificate "Apple Distribution: Y"
Provisioning profile doesn't include signing certificate

The short answer

Your certificate and your profile are no longer a pair. A provisioning profile embeds a fixed list of certificates it will accept. If the certificate was regenerated, revoked, or created on a different machine after the profile was issued, the profile still lists the old one and refuses the new one.

The fix is a regeneration, in this order:

  1. Settle the certificate first. Either use the .p12 you already hold, or create a new Apple Distribution certificate and export it — but decide now, because the profile is about to be pinned to whichever one you choose.
  2. Go to Certificates, Identifiers & Profiles → Profiles, open the failing profile, and click Edit.
  3. Tick the certificate you actually hold. This is the step people skip — the profile does not pick it up automatically.
  4. Save, download the regenerated .mobileprovision, and replace the old file everywhere it lives: your project, and any CI secret holding a base64 copy of it.

Never regenerate the profile first and the certificate second. The profile is pinned at the moment it is issued, so doing it in that order produces a profile pinned to a certificate you are about to replace.

Why this happens

This error is confusing because both halves look fine on their own. The certificate is valid. The profile has not expired. Xcode still refuses, and the message names two things that both appear to exist.

The reason is that a .mobileprovision file is not a pointer to your certificate. It is a CMS-signed property list that contains a copy of every certificate it will accept, as DER data, under a key called DeveloperCertificates. Signing works only if the certificate doing the signing is byte-for-byte one of the certificates in that array.

So the pairing is decided once, when Apple issues the profile, and it never updates. Any of these breaks it:

  • You regenerated the distribution certificate — even for the same team and the same name. A regenerated certificate is a different certificate with a different fingerprint.
  • Someone else on the team created a certificate and you are building with theirs.
  • The certificate was revoked, which invalidates every profile that embedded it.
  • You restored a .p12 from a backup that predates the current profile.

Reading the profile yourself

You do not have to guess. A .mobileprovision is a CMS blob wrapping XML, and you can decode it in one command:

security cms -D -i credentials/ios/profile.mobileprovision

On Linux, where security does not exist, OpenSSL reads the same structure:

openssl smime -inform DER -verify -noverify -in profile.mobileprovision

In the output, find the DeveloperCertificates array. Each <data> entry is a base64 DER certificate. To compare one against the certificate inside your .p12, take the SHA-1 fingerprint of each and see whether your certificate's fingerprint appears in the profile's list:

# fingerprint of the certificate you hold
openssl pkcs12 -in dist.p12 -clcerts -nokeys -passin pass:YOURPASSWORD \
  | openssl x509 -noout -fingerprint -sha1

If that fingerprint is not among the profile's embedded certificates, the profile cannot sign with it, and no amount of cleaning derived data will change that.

Why "clean the build folder" is bad advice

Most search results for this error suggest clearing derived data, restarting Xcode, or toggling automatic signing. Those occasionally appear to work, because automatic signing silently issues a new profile behind your back that happens to include your current certificate. That fixes the symptom on one machine and leaves CI broken, because CI is still using the committed profile. The pairing is the problem; fix the pairing.

Catching it before you build

This is one of the checks that made us write a preflight command. The pairing is fully determinable before a build starts — you have both files on disk — so failing forty minutes into an archive is avoidable. leas doctor compares the fingerprint of the certificate in your .p12 against the certificates the profile embeds and says so:

▸ iOS
  ✓ Distribution certificate    Apple Distribution: Kaya Labs — valid until 2027-09-25
  ✗ Provisioning profile        "Kaya App Store" does not list your distribution certificate
      → Regenerate the profile after selecting the certificate you actually hold.

Set up leas in 10 minutesFree, MIT licensed, and it never receives your signing keys.

If that didn’t fix it

  • CI still failing after it works locally. The base64 secret holding the profile is a copy, not a link. Regenerating the file does not update it. Re-encode and set the secret again.
  • Two profiles with the same name. Apple allows it, and Xcode may install the older one. Match on UUID rather than name — security cms -D -i profile.mobileprovision prints it — and delete stale copies from ~/Library/MobileDevice/Provisioning Profiles/.
  • The profile is for a different App ID. A wildcard profile will not cover an explicit App ID that has entitlements attached. Compare the profile's application-identifier against your bundle identifier exactly.