~/fix/"Embedded binary is not signed with the same certificate as the parent app" — fix
2026·04·20
fix20 April 2026#app-development

"Embedded binary is not signed with the same certificate as the parent app" — fix

Why iOS rejects an app whose extension, framework, or watchOS app is signed by a different identity than the host — and the safe ways to make signatures match.

TL;DRiOS validates that every embedded binary (app extensions, frameworks, watch apps, app clips) was signed by the same Team ID as the host app. The mismatch is almost always either (a) a stale framework left over from a previous developer, or (b) a build script that re-signs only the host. Re-archive with a clean DerivedData and a single signing identity, and the error goes away.
Embedded binary is not signed with the same certificate as the parent app. Verify the embedded binary target's code sign settings match the parent app's.

What iOS is actually checking

When `installd` (on-device) or App Store Connect's static analyzer validates an `.ipa`, it walks the bundle structure and verifies that every embedded `.appex`, `.framework`, `.dylib`, and watch app inside `Frameworks/`, `PlugIns/`, and `Watch/` shares the same Team ID — and ideally the same exact certificate fingerprint — as the host `.app`'s signature. If anything mismatches, installation or upload fails with this error.

Diagnose first — see who signed what

find <Path>.app -type d -name '*.appex' -o -name '*.framework' -o -name '*.app' | xargs -I{} codesign -dvvv {}

Look at `Authority=` and `TeamIdentifier=` for each binary. If even one shows a different Team ID, that's the offender.

Fix path A — stale framework from a previous build

  1. Quit Xcode.
  2. rm -rf ~/Library/Developer/Xcode/DerivedData/<YourApp>-*
  3. rm -rf ios/build (if you have it from Expo / RN).
  4. In Xcode → Product → Clean Build Folder (Shift+Cmd+K).
  5. Re-archive.

This handles ~70% of cases — a CocoaPods or SwiftPM update changed who built a framework, but a pre-built copy from the previous Team ID was still cached.

Fix path B — the embedded target uses a different signing identity

Open each embedded target's Signing & Capabilities tab. If "Automatically manage signing" is on for the host but off for the extension (or vice versa), Xcode will sign each with whatever's convenient. Pick one mode and apply it to every target. For manual signing, every target must use a profile from the same team.

Fix path C — third-party SDK ships pre-signed binaries

Some commercial SDKs (notably analytics, AR, and DRM SDKs) ship `.framework` bundles that are pre-signed by the vendor. Xcode is supposed to re-sign them at copy time. If `Code Sign On Copy` is off in your `Embed Frameworks` build phase, the original signature stays. Toggle it on for every embedded framework.

Edge cases I've hit on real engagements

  • An app clip embedded inside the host had a separate `.entitlements` file pointing at a different App ID prefix — it was technically a different team to iOS.
  • Carthage `--no-use-binaries` rebuilds frameworks locally but a single dev had `--use-binaries` cached; CI matched, his machine didn't.
  • An old `.framework` symlink under `ios/Pods/` survived a `pod install` because the directory structure had changed (CocoaPods doesn't always remove orphans). `rm -rf ios/Pods && pod install` cleaned it.
  • The host app and a watchOS extension belonged to two different App IDs in the same team — App Store rejected the upload until the watchOS App ID prefix was updated.

Verify the fix before re-uploading

codesign --verify --deep --strict --verbose=2 <Path>.app

Should print `valid on disk` and `satisfies its Designated Requirement`. If you see `a sealed resource is missing or invalid`, run the diagnose step again — there's still a mismatched binary inside.

Related fixes