"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.
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
- Quit Xcode.
- rm -rf ~/Library/Developer/Xcode/DerivedData/<YourApp>-*
- rm -rf ios/build (if you have it from Expo / RN).
- In Xcode → Product → Clean Build Folder (Shift+Cmd+K).
- 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>.appShould 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.