iOS · build & submit

Distribution certificate hasn’t been imported successfully

Distribution certificate with fingerprint ... hasn't been imported successfully
The certificate could not be imported into the keychain

The short answer

Check them in this order — the first is the most common by a wide margin.

  1. The .p12 has no private key in it. Exporting the wrong row in Keychain Access produces a file containing only the certificate, which cannot sign anything. Verify:
    openssl pkcs12 -in dist.p12 -nocerts -passin pass:YOURPASSWORD | head -1
    You want a BEGIN PRIVATE KEY line. Nothing, or an error, means you exported the certificate alone — go back and export the parent row with the disclosure triangle, which contains both.
  2. The password is wrong or empty. An empty export password is legal and a frequent surprise; try an empty string explicitly before assuming corruption.
  3. The Apple WWDR intermediate certificate is missing or expired on the machine doing the import, which makes an otherwise valid certificate untrusted. Install the current one from Apple's certificate authority page.

Why this happens

A distribution certificate on its own is a public document. It proves nothing and signs nothing. What matters is the private key generated alongside it, which never leaves the machine that created the signing request — and a .p12 is a container meant to hold both.

Keychain Access presents these as a parent row (the certificate) with a child row (the private key) hidden behind a disclosure triangle. Selecting and exporting the certificate row alone produces a perfectly valid, perfectly useless file: an import succeeds, and signing later fails, which is why the error arrives at a confusing distance from the mistake.

This is also the reason a certificate cannot be meaningfully "downloaded again" from the Apple developer console. What you download there is the public certificate. If the private key is gone — wiped machine, no backup — the certificate is unusable and the only path is to revoke it and issue a new one.

The OpenSSL 3 wrinkle

If you are inspecting the file on a machine with OpenSSL 3 and it fails to read at all, that may not be the file's fault. Keychain Access still exports using older PKCS#12 ciphers that OpenSSL 3 disabled by default. Add -legacy:

openssl pkcs12 -in dist.p12 -clcerts -nokeys -legacy -passin pass:YOURPASSWORD

Tools that read these files should try both forms before reporting a problem, because the difference is in the reader, not the certificate.

Keychain state on CI

On a build machine there is a further trap. Importing into the login keychain leaves codesign waiting on an interactive permission prompt that nobody will ever answer, so the build appears to hang rather than fail. The correct pattern is a throwaway keychain, unlocked explicitly, with the partition list set so that codesign may use the key without prompting — then deleted afterwards.

Catching it before you build

The private-key case is the one worth catching early, because the symptom otherwise appears much later than the mistake. leas doctor opens the .p12 with the password it will actually build with and reports the identity and expiry it found:

▸ iOS
  ✓ Xcode                       Xcode 26.6
  ✓ Distribution certificate    Apple Distribution: Kaya Labs — valid until 2027-09-25
  ✓ Provisioning profile        "Kaya App Store" · com.kaya.app — valid until 2027-06-01

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

If that didn’t fix it

  • The import succeeds and signing still fails. That is the missing private key case — the file imported fine because a certificate alone is valid. Run the -nocerts check above.
  • It works for one teammate and not another. Whoever created the signing request holds the private key. Everyone else needs the exported .p12, not the certificate downloaded from the developer console.
  • The build hangs instead of failing. That is a keychain prompt waiting for a human on a machine with no human. See the keychain note above.