ITMS-90034: How to Fix “Missing or invalid signature”
By Mehdi Azizi
Published , 8 min
ITMS-90034 means your build isn't signed with a valid distribution certificate. Check its signature with codesign, then make a new store build with EAS.
ITMS-90034 shows up when you upload your build to App Store Connect. It says your app, or one of its components, isn't signed with an Apple submission certificate, meaning a valid distribution certificate. The fix: find which bundle is signed wrong and why, then make a new build signed for the App Store.
This guide sticks to the error. If certificates and profiles are still fuzzy for you, read iOS developer certificate and provisioning profile first. Here you'll get the message to read, a decision tree, the commands that inspect your IPA, and the fix using EAS-managed credentials. For the EAS part, I read the EAS CLI 24.10.0 code that picks the certificate.
What does the ITMS-90034 error mean?
Here's its usual form, with example names:
ITMS-90034: Missing or invalid signature. The bundle 'com.example.myapp' at bundle path 'Payload/MyApp.app' is not signed using an Apple submission certificate.
In 2026, on Apple's forums, it also shows up as "Validation failed (409) Missing or invalid signature", followed by the same text and "(ID: 90034)".
The "submission certificate" is the distribution certificate. Apple's help page on certificates spells it out: development certificates let you run your app on your devices, distribution certificates let you distribute it or upload it to App Store Connect.
Read the path in the message: it points to the faulty bundle. Payload/MyApp.app means the app itself. A path ending in .appex means an extension, like a widget. A path ending in .framework means an embedded library.
This isn't a reviewer rejection. Validation fails at upload or while the build is processing, before TestFlight: this build will never reach your testers.
The decision tree: from message to fix
Each row matches a clue you'll find in the message, in the commands from the next section, or in the EAS logs. Go through them in order: the first one that matches is your lead.
| What you see | Likely cause | Fix |
|---|---|---|
Path ending in .appex | Extension signed wrong | Declare the extension |
Signature=adhoc | Unsigned build | Store profile build |
Apple Development | Development build | Store profile build |
ProvisionedDevices read | Internal (ad hoc) build | Store profile build |
sealed resource | IPA modified afterward | Rebuild |
| EAS: "no longer valid" | Revoked certificate | New certificate |
| Everything is valid | Issue on Apple's side | Resubmit, then report it |
Inspect your IPA in four commands
Download the IPA from the build page on expo.dev, then open a terminal on your Mac.
1. Who signed the app?
unzip -q MyApp.ipa -d ipa
codesign -dv --verbose=4 ipa/Payload/*.app 2>&1 | grep -E "^(Identifier|Authority|Signature|TeamIdentifier)="
codesign writes to standard error, hence the 2>&1. According to Apple's technical note TN3161, each Authority line is a link in the chain of trust. The first one should start with Apple Distribution: or iPhone Distribution:, followed by your team name. The second label belongs to the older iOS Distribution type: according to its code, EAS CLI 24.10.0 still creates certificates of that type. If you see Apple Development:, it's a development build. If you see Signature=adhoc with no Authority line at all, the binary isn't signed by any certificate.
2. Was the app modified after signing?
codesign --verify --deep --strict -vv ipa/Payload/*.app
You want to see valid on disk, then satisfies its Designated Requirement. TN3161 explains what this check guarantees: every expected file is there, none was added, none was modified. On a test bundle I signed and then tweaked, the command returns a sealed resource is missing or invalid, then file modified: followed by the changed file. The --deep option is for verifying here, never for signing: on Apple's forums, an engineer from the support team advises against using it to sign.
3. Which profile is embedded?
security cms -D -i ipa/Payload/*.app/embedded.mobileprovision -o profil.plist
plutil -extract ProvisionedDevices xml1 -o - profil.plist
plutil -extract ExpirationDate raw profil.plist
These are the commands from the TN3125 note on profiles. An App Store profile contains no device list: the second line should return Could not extract value. If it prints device identifiers, it's an ad hoc profile, the kind used by an internal build. The third line gives the profile's expiration date.
4. Are the extensions and frameworks signed the same way?
find ipa/Payload/*.app \( -name "*.appex" -o -name "*.framework" \) \
-exec sh -c 'echo "$1"; codesign -dvv "$1" 2>&1 | grep -m1 "^Authority="' _ {} \;
Every component should show the same Authority line as the app. If one of them differs, that's the one the message is pointing at.
If you want to check before uploading, TN3161 recommends altool, the same check as the Validate App button in Xcode. It needs an App Store Connect API key, whose AuthKey_<KEY_ID>.p8 file goes in ~/.appstoreconnect/private_keys:
xcrun altool --validate-app -f MyApp.ipa -t ios --api-key <KEY_ID> --api-issuer <ISSUER_ID>
Fixing it with EAS, cause by cause
An internal or development build sent to Apple
According to Expo's eas.json documentation, builds with "distribution": "internal" aren't signed for the stores: they use an ad hoc profile. Only a profile with store distribution, the default value, produces a build you can upload. The safest move is to submit the build you just made, without picking it by hand:
eas build --platform ios --profile production --auto-submit
If you use eas submit --path, make sure the file really is your latest store build. On Apple's forums, one team found out their upload tool kept sending an old IPA that was committed in git.
A forgotten extension
Each extension is a separate bundle, with its own identifier and its own profile. In an Expo project with native generation, Expo's page on iOS app extensions asks you to declare them in extra.eas.build.experimental.ios.appExtensions. EAS CLI then knows about them before the build, and creates or validates their credentials. Most libraries that add an extension write this declaration for you through their plugin.
Solys, my mini-game alarm clock, ships four extensions: a widget and three Screen Time extensions. All four are declared in its config, and EAS has a profile for each. An extension added by hand in Xcode, without this declaration, is the prime suspect when the message shows a path ending in .appex.
A revoked or expired certificate
Apple's certificates page is clear: you can no longer upload a build signed with an expired or revoked certificate. A build that's already uploaded but not yet submitted can even switch to Invalid Binary if its certificate was revoked.
The EAS CLI 24.10.0 code shows when this goes unnoticed:
- Interactive build, signed in to Apple: EAS compares its certificate with the ones still valid at Apple. If it's gone, it shows "Current distribution certificate is no longer valid in Apple Dev Portal" and lets you pick or create one.
- Interactive build, not signed in: EAS only checks the dates and warns you that it's skipping validation with Apple.
- Non-interactive build, in CI: EAS shows "Distribution Certificate is not validated for non-interactive builds" and signs anyway.
In CI, EAS doesn't recheck the certificate itself: a revocation might only show up at upload. The fix: run an interactive build signed in to your Apple account, or use eas credentials --platform ios, Build Credentials menu, then "Distribution Certificate: Add a new one to your account". Profiles that contained the old certificate become invalid: EAS checks them on the next build and regenerates them. Apple's limits on the number of certificates are covered in the iOS developer certificate guide.
A binary modified after signing
The signature seals the code, resources and metadata with hashes, as Apple's TN3126 note explains. Unzipping the IPA to change a file and then zipping it back breaks that seal. Make the change in your config, then rebuild. Never touch the IPA EAS produces.
Same logic for code stored in the wrong place, for example inside a .zip archive: the App Store can't re-sign it. Apple lists the allowed locations on its page about placing content in a bundle.
Local credentials
If your EAS profile uses "credentialsSource": "local", your credentials.json file points to a .p12 certificate and a .mobileprovision profile. Check the profile with the commands from step 3: it must be an App Store profile and contain your current distribution certificate. And keep these files out of your repo, just like API keys in an Expo app.
When everything is valid
There's one frustrating case left. On Apple's forums, some developers see the error disappear by resubmitting the same build without changing anything. In August and September 2026, two threads describe the opposite: new certificate and profile, verified signature, and it still fails. In one of them, an Apple engineer recommends a bug report with the IPA, the signature analysis and the Transporter logs, then contacting App Store Connect.
So resubmit once with a new build number. If the error comes back while your four commands come out clean, report it to Apple with those items. Don't revoke your certificate on reflex: it fixes nothing more and it invalidates your profiles.
Upload your build without nasty surprises
Checking a signature takes two minutes before you upload. The other automated checks call for the same rigor, like ITMS-90725 for the Xcode version or ITMS-90683 for permission strings. The full path from build to upload, without a Mac, is in publish an iOS app without a Mac.
Reviewer rejections need more perspective: the approach is on the app rejected by Apple page, and the most common reasons are in why Apple rejects an app.
To check your submission before uploading, the Review Kit bundles my checklist and Claude Code skills that review your project. If your upload is stuck and you want a human eye on it, book an hour with me: we go through your project on a video call, on your screen. And if you're getting ready for your first release, take the free diagnostic: it puts the steps in order and sends you my Apple anti-rejection checklist.
Frequently asked questions
Is ITMS-90034 an App Review rejection?
No. It's an automated validation run when the build is uploaded, before TestFlight and before any review. Nobody opened your app: Apple just found that its signature doesn't come from a valid distribution certificate.
Do I need to revoke my distribution certificate to fix ITMS-90034?
Only if it's compromised or already invalid. Revoking a working certificate invalidates your profiles without fixing the cause. Start by reading your IPA's signature with codesign, then fix whatever the decision tree points to.
Can I fix ITMS-90034 with an over-the-air update?
No. The signature is part of the binary, and the rejected build will never be usable. You need to produce a new, properly signed binary and upload it again.
Why does the error mention my widget and not my app?
Because the widget is a separate bundle, signed with its own profile. If it isn't declared to EAS or was signed differently, it makes the whole upload fail. Declare the extension in your config and rebuild.
What if codesign says everything is valid?
Also check the embedded profile and every extension. If everything is clean, resubmit once with a new build number. If the error persists, send Apple a report with the IPA, the codesign output and the upload logs.

