You shipped a Replit Agent project to iOS, wrapped it in Capacitor or built it through Expo Application Services, and the moment the upload finished, Apple's transporter sent back ERROR ITMS-90035: Invalid Signature. The build never reached App Review. The rejection email landed in your inbox within minutes. This page is a recovery workflow, not an explainer: what to run first, what the output tells you, and the order to make the fixes so the next upload passes.
Short answer
Fixing ITMS-90035 is a sequence of five steps, in order. First, read the path fragment in the rejection email to identify which file broke the seal. Second, unzip the IPA and run codesign -dvvv against the main binary and every embedded framework to confirm the signing authority and team identifier. Third, decide which of three categories the failure falls in: wrong signing identity (Development or Ad Hoc instead of Distribution), mismatched team identifier on an embedded framework, or post-signing modification of a resource. Fourth, re-archive with the correct Distribution identity selected, or re-run the Expo Application Services Build after rotating credentials. Fifth, re-upload through Transporter or eas submit. According to Apple's developer forum thread on ITMS-90035, the same three categories cover almost every reported case across years and tools.
What you should know
- The rejection email contains the diagnostic. The path fragment after Code object is not signed at all names the exact file that broke the signature. Read it before running any command.
- codesign is the canonical diagnostic tool. Apple's Code Signing Troubleshooting Index (TN2407) directs every signature investigation through
codesign -dvvvandcodesign --verify --deep --strict. - Replit Agent does not sign anything. The signing layer is whichever wrapper produced the IPA: Xcode for Capacitor, Expo Application Services Build for React Native, or a third-party wrapper service. The fix lives there.
- A Distribution identity is required for App Store uploads. A Development or Ad Hoc identity passes local install tests but fails the transporter check immediately.
- Embedded frameworks have to carry the same team identifier as the main binary. A single CocoaPod or Swift Package signed by a different team invalidates the outer seal.
- Post-signing modifications break the seal. Any CI step that touches the IPA after codesign runs (asset replacement, plist edit, zip recompression) triggers ITMS-90035 even when the original signature was valid.
- Keychain rot is a real cause. An expired Apple Worldwide Developer Relations intermediate certificate in the System or Login keychain breaks every signature produced on the machine until removed.
What does the path fragment in the ITMS-90035 email actually tell you?
The rejection email's second sentence carries the diagnostic. The format is one of two patterns. Either Code object is not signed at all followed by a path like Payload/YourApp.app/Frameworks/SomeFramework.framework/SomeFramework, or A sealed resource is missing or invalid followed by a file inside the bundle. The path tells you whether the problem is the main binary, an embedded framework, or a resource file. That decision drives the next command you run.
If the path points at the main binary (Payload/YourApp.app/YourApp with no framework segment), the signing identity on the archive itself was wrong. Almost always Development or Ad Hoc instead of Distribution. If the path points inside Frameworks/, the failure is an embedded library carrying a different team identifier than the outer bundle. If the path points at an asset file, an Info.plist, or the bundle's _CodeSignature/CodeResources file, a post-signing modification broke the seal. According to Apple's developer forum reference thread on ITMS-90035, the three categories are mutually exclusive: each ITMS-90035 case sits in exactly one of them, and reading the path fragment correctly cuts the troubleshooting space by two-thirds.
Save the rejection email before deleting it. The path fragment is the only piece of state Apple gives you about the failure, and the same information does not appear inside App Store Connect.
How do you run codesign against the IPA to confirm what broke?
The codesign workflow is short. Rename the .ipa to .zip, unzip it, then run two commands. The first prints the signature details on the main binary:
codesign -dvvv Payload/YourApp.app/YourApp
The output lists the signing identity under Authority lines, the team identifier, and the entitlements. For an App Store build, the first Authority line must read Apple Distribution followed by your team name and team ID. Apple Development or iPhone Developer is the cause of the rejection.
The second command verifies the whole bundle including embedded frameworks:
codesign --verify --deep --strict --verbose=2 Payload/YourApp.app
This pass-through runs the same checks Apple's transporter runs on upload. It prints valid on disk and satisfies its Designated Requirement when the bundle is clean, and prints the first failing path when it is not. The failing path almost always matches the one in the rejection email. Run the same codesign -dvvv command against each item in Payload/YourApp.app/Frameworks/ to confirm every framework carries the same team identifier as the main binary. A mismatch on any single framework breaks the outer seal.
How do you decide which of the three categories the failure sits in?
The combination of the email path and the codesign output sorts the failure quickly. The next table maps each category to the diagnostic signal and the fix:
| Category | Diagnostic signal | Fix action |
|---|---|---|
| Wrong signing identity | codesign Authority on main binary reads Apple Development or iPhone Developer | Re-archive with the Distribution identity selected in Signing and Capabilities |
| Mismatched team on framework | Authority on the main binary is Distribution, but one Frameworks/*.framework binary shows a different team identifier | Add Podfile post_install hook setting DEVELOPMENT_TEAM, or correct the Swift Package signing settings |
| Post-signing modification | codesign --verify reports A sealed resource is missing or invalid against a specific resource path | Remove the CI step that runs after codesign, or move asset replacement before the archive step |
Nothing else accounts for the rejection at production scale. Apple's transporter does not run secondary checks that produce ITMS-90035; the error is exclusively about the codesign seal. If codesign --verify returns clean on the local machine but the upload still fails, the next suspect is keychain rot on the build machine: an expired Apple Worldwide Developer Relations intermediate certificate visible under World in Keychain Access. Apple's PKI certificate authority page lists the current intermediates, with the G3 certificate as the active root for iOS Distribution.
How do you re-sign and re-archive without breaking anything else?
The re-archive workflow differs by build path. For Capacitor opened in Xcode, the steps are: open the workspace in Xcode 26, select the project in the navigator, open Signing and Capabilities, set Team to the correct Apple Developer team, confirm Automatically manage signing is checked unless you maintain manual profiles, select Any iOS Device as the destination (never a simulator), then Product, Archive. The Organizer window shows the new archive. Distribute App, then App Store Connect, then Upload. Verify the resulting IPA passes the codesign checks above before clicking Upload, not after.
For Expo Application Services Build, rotate credentials first, then build:
eas credentials
eas build --platform ios --profile production --clear-cache
eas submit --platform ios --latest
The eas credentials command opens an interactive flow to view, regenerate, or remove the Distribution certificate and provisioning profile. According to the Expo Application Services managed credentials reference, the credentials are stored on Expo's servers per Apple Developer team. Regenerating them issues fresh artifacts that the next build picks up automatically. The --clear-cache flag on the build command forces a clean signing pass and avoids the case where the previous broken artifact gets cached and re-uploaded.
For a third-party wrapper service, the recovery is the same idea executed through the wrapper's dashboard: delete the stored .p12 and provisioning profile, upload a fresh Distribution certificate exported from the Apple Developer portal, and trigger a new build. PTKD.com (https://ptkd.com) often sees the wrapper case in builds where the developer pasted a .p12 exported from a teammate's machine; the team identifier inside the certificate did not match the team that owns the bundle identifier, and every build came back with ITMS-90035 until the certificate was replaced with one exported from the owning team.
What about the keychain side of the fix?
The local Keychain Access flow takes five minutes and catches a class of failures the codesign output does not surface directly. Open Keychain Access on the build Mac, select the System keychain, set View to Show Expired Certificates, search for world, and delete any Apple Worldwide Developer Relations entries dated before the current intermediate. Repeat on the Login keychain. Then download the current intermediate from Apple's PKI certificate authority page and install it into both keychains.
This step matters because an expired intermediate certificate makes every Distribution certificate on the machine appear invalid to codesign even when the certificates themselves are fine. The transporter then rejects the signature with ITMS-90035 because the chain validation fails on Apple's side. The symptom is identical to a wrong-identity case, but the cause is local. Per Apple's developer forum thread on ITMS-90035, this is the single most common cause of repeated ITMS-90035 rejections on machines that previously worked.
What to watch out for
- Re-uploading the same archive after rotating the certificate. The signature is baked into the IPA at archive time. Rotating Keychain entries does not retroactively re-sign a built archive. Always re-archive.
- A Pod that pins its own DEVELOPMENT_TEAM during pod install. Add a Podfile
post_installhook that setsCODE_SIGN_STYLEtoManualand assigns the sameDEVELOPMENT_TEAMto every Pod target. The Codemagic Xcode 14 code signing guide provides the canonical snippet. - CI steps that run after codesign. Any zip recompression, asset replacement, plist edit, or notarization-style step that touches the IPA after the archive invalidates the bundle. Move those steps before the archive or remove them.
- Non-ASCII characters in the bundle identifier or file names. Replit Agent occasionally invents file names with smart quotes or accented characters. The validator silently rejects the resulting signature. Stick to ASCII across the bundle identifier, asset catalog entries, and every framework file name.
- Selecting a Generic iOS Device versus Any iOS Device. Generic is allowed but inconsistent across Xcode versions. Any iOS Device produces a predictable Distribution archive every time. Use Any iOS Device.
- Trusting a colleague's machine to upload. A teammate's keychain is not a fix for the original machine. The next rejection lands again the moment the original developer tries to upload from their own Mac. Fix the machine that produced the build.
Key takeaways
- Read the rejection email path fragment before running any command. It identifies which of the three categories the failure sits in and cuts the troubleshooting space immediately.
- codesign -dvvv on the main binary and codesign --verify --deep --strict on the bundle are the only two diagnostics worth running first. Everything else follows from their output.
- Re-archive after the fix; never re-upload the broken IPA. The signature is part of the bundle, and rotating Keychain or EAS credentials does not change bytes that are already on disk.
- Embedded frameworks have to carry the same team identifier as the main binary. A Podfile
post_installhook removes the most common failure mode in Capacitor builds. - For Replit Agent flows that go through a wrapper, an external scan of the compiled IPA against OWASP MASVS before each App Store Connect upload catches the categories that codesign does not surface, including post-build resource modifications and non-ASCII bundle entries. PTKD.com (https://ptkd.com) is one of the platforms focused on pre-submission scanning of compiled mobile bundles for that purpose.




