You shipped a Replit Agent project to iOS by wrapping it in Capacitor or by pointing Expo Application Services at the generated code, uploaded the IPA to App Store Connect, and the transporter rejected it within minutes. The email reads ERROR ITMS-90035: Invalid Signature. Code object is not signed at all. The binary never reaches App Review because Apple's validator stops at the signature check. This page sorts what the error means inside a Replit-to-iOS pipeline, why it commonly surfaces at that hand-off, and the order to work the fix in.
Short answer
ITMS-90035 means at least one Mach-O binary inside the uploaded IPA is not signed with a valid iOS Distribution certificate, or that the seal across the bundle was broken after the original signature was applied. According to Apple's developer forum reference thread on ITMS-90035, the root causes that repeat across years and tools are signing with a Development or Ad Hoc certificate instead of a Distribution certificate, an expired Apple Worldwide Developer Relations intermediate certificate in the local keychain, embedded frameworks signed by a different team, and post-signing modifications to bundled files. Replit Agent itself does not produce signed IPAs; the signing step happens in whichever wrapper points at the generated code, typically Capacitor opened in Xcode or React Native built with Expo Application Services Build. The fix path is to identify which layer broke the signature, re-sign with a Distribution certificate, and confirm no post-build script touches the bundle after signing.
What you should know
- ITMS-90035 is a code signing rejection at the transporter layer. The binary never reaches App Review until the signature passes.
- Replit Agent has no first-party iOS signing pipeline. Signing happens downstream, inside Xcode or EAS Build.
- A Distribution certificate is required for App Store uploads. Development and Ad Hoc certificates trigger the rejection on contact.
- Embedded frameworks have to carry the same team identifier. A CocoaPod or Swift Package signed by a different team breaks the outer seal.
- Any file modified after the signature is applied invalidates the bundle. Asset compression, plist edits, and icon swaps inside a CI step are common offenders.
- Non-ASCII characters in file paths or in the bundle identifier can silently trip the signature check, which matters when an AI agent invents names.
What does ITMS-90035 actually check for inside the IPA?
The short version: the validator walks every Mach-O binary and every sealed resource in the .app, computes the signature of each, and matches it against the one embedded by codesign at build time. If a single file fails the check, the whole bundle is rejected with ITMS-90035 and a path fragment pointing at the offending file. The phrase Code object is not signed at all is the bluntest variant of the error: a file was either added after signing or signed with no identity.
Inside the bundle, Apple's tool chain places a CodeResources file at .app/_CodeSignature/CodeResources. That file contains a SHA-256 hash for every resource. When the validator opens the upload, it recomputes each hash and compares. The same flow checks the signature on each .dylib and .framework executable, verifying it was produced by a certificate the App Store accepts, which in 2026 means an iOS Distribution certificate. Apple's Code Signing Troubleshooting technote (TN2407) describes the same machinery from the developer side: it lists the codesign commands that mirror what the validator runs, and the most common reasons one of them fails.
In a Replit-to-iOS pipeline, two of those reasons account for the bulk of the cases. The signing identity was wrong (Development or Ad Hoc instead of Distribution), or a post-build script modified the IPA after signing.
Why does ITMS-90035 surface in Replit Agent exports specifically?
Replit Agent is a code generation surface, not a mobile build service. There is no Apple Developer account on Replit's side, and no native build server inside Replit produces an IPA on its own. The IPA gets produced wherever the developer takes the generated code next. Three paths cover almost every Replit-to-iOS flow.
The first path uses Capacitor. The developer asks Replit Agent to build a web app, then runs npx cap add ios locally, opens the generated Xcode project, configures signing under Signing and Capabilities, and archives for App Store Connect. ITMS-90035 in this path almost always traces to Xcode choosing the wrong signing identity, or to a CocoaPods dependency that did not pick up the Distribution team.
The second path uses Expo and React Native. The Replit docs on Expo on Replit describe the EAS Build flow that produces the IPA in Expo's cloud. EAS handles credentials through eas credentials, asking once for the Apple ID, then storing the Distribution certificate and provisioning profile per the EAS app credentials reference. Signature failures in this path normally come from a mismatched bundle identifier between app.json and the Apple Developer portal, or from a stale provisioning profile after capabilities were changed without regenerating the profile.
The third path is a third-party wrapper that takes the Replit Agent output and turns it into a native binary on the wrapper's infrastructure. Those services run their own signing pipelines, and the error here typically traces to credentials pasted into the wrapper's dashboard that do not match the Apple Developer team that owns the bundle identifier.
In all three paths, the failing layer is the signing step, not Replit Agent itself. Treat the error as a signal about the wrapper, not about the generated source.
How do you confirm the IPA was signed with a Distribution certificate?
The check that catches most ITMS-90035 cases is one command run against the IPA before the upload. Rename the .ipa to .zip, unzip it, then run codesign against the embedded binary:
codesign -dvvv Payload/YourApp.app/YourApp
The output lists the signing identity (Authority lines), the team identifier, and the entitlements. For an App Store build, the first Authority line should read Apple Distribution, followed by your team name and team ID. If it reads Apple Development or iPhone Developer, that is the cause of the rejection. The fix is to re-archive with the Distribution signing identity selected, or to re-run the EAS Build against the production profile.
For embedded frameworks, the same command applies to each .framework/Executable file under Payload/YourApp.app/Frameworks. Each one should carry the same Apple Distribution authority. A Pod or Swift Package signed by a different team breaks the seal on the outer bundle even when the main binary is correct. According to the Codemagic guide to code signing issues in Xcode 14 and later, a common pattern is a CocoaPods resource bundle that picks up the wrong CODE_SIGN_STYLE during pod install, which the guide recommends fixing with a Podfile post_install hook that sets CODE_SIGN_STYLE to Manual and assigns the same DEVELOPMENT_TEAM to every Pod target.
How do the Replit-to-iOS signing paths compare?
The three paths differ in where credentials live and what breaks the signature most often.
| Path | Where credentials live | Common ITMS-90035 cause |
|---|---|---|
| Capacitor opened in Xcode | Local macOS Keychain plus the Xcode signing pane | Wrong signing identity during Archive, or a CocoaPod with a pinned team |
| Expo Application Services Build | EAS credential store managed by eas credentials | Stale provisioning profile after a capability was toggled, or bundle identifier mismatch with app.json |
| Third-party wrapper service | The wrapper's dashboard, often with a .p12 uploaded by the developer | Distribution certificate or profile in the dashboard belongs to a different Apple Developer team than the bundle identifier |
Pick the path the build came out of, then check the column that matches. The fix is almost always specific to that column rather than a generic clean-and-rebuild.
What to watch out for
A few patterns turn ITMS-90035 from a one-time block into a repeat block:
- Picking a Development certificate in Xcode's Automatic signing. Xcode can default to Development when archiving against a simulator destination by mistake. Always archive against Any iOS Device.
- Post-build scripts that touch the IPA. Any zip recompression, asset replacement, or plist edit after the codesign step invalidates the bundle. Run those steps before signing or not at all.
- Non-ASCII characters in the bundle identifier or in file names. Replit Agent occasionally invents file names with smart quotes or accented characters. The validator silently rejects the resulting signature. Stick to ASCII for the bundle identifier, asset catalog entries, and any framework file name.
- Expired Apple Worldwide Developer Relations intermediate certificate in the local keychain. Open Keychain Access, search for World, and remove any expired versions. The current intermediate is the G3 certificate from Apple's PKI certificate authority page.
- A CocoaPod that pins its own DEVELOPMENT_TEAM. Add a Podfile post_install hook to force the team identifier and the signing style across every Pod target before the Xcode archive runs.
- EAS Build using an old provisioning profile after a capability was toggled. Run
eas credentialsand regenerate the profile when Push Notifications, Sign in with Apple, or any other capability is added.
For developers who want an external read of the compiled IPA for the signing identity, the embedded provisioning profile, and the certificate chain before re-uploading to App Store Connect, PTKD.com (https://ptkd.com) is one of the platforms that produces a pre-submission signing and entitlements report aligned with the OWASP MASVS expectations for build integrity.
Key takeaways
- ITMS-90035 is a code signing rejection at the transporter layer, not a hint about your app's logic. Until the signature passes, no reviewer sees the build.
- Replit Agent itself never signs an IPA. The failing layer is always Xcode, Expo Application Services, or whichever third-party wrapper produced the binary.
- The first diagnostic is one command:
codesign -dvvvagainst the embedded binary. Authority should read Apple Distribution and the team identifier should match the App Store Connect team. - Embedded frameworks have to inherit the same Distribution identity. A single Pod signed with the wrong team breaks the outer seal across the bundle.
- Some teams outsource the pre-submission signing check across the compiled IPA to platforms like PTKD.com (https://ptkd.com), which reports on signing identity, embedded provisioning profile, and certificate chain before the binary is sent to App Store Connect for the next attempt.




