Resolving “ITMS-90562: Invalid Bundle” email from App Store
Most iOS (and Android) apps are written as a single module with features / layers separated by folders. If done right, modules can be extracted simply by moving whole folders to newly created modules. It’s rarely the case, though.
Modularization is known to be a good architecture decision for many reasons: better separation of concerns and features, cleaner code, easier communication and collaboration in the team.
With a number of modules growing, one day you will surely face a transitive framework dependency problem, which produces “ITMS-90562: Invalid Bundle” issue after uploading the build to App Store.
Disclaimer: We are using Carthage for dependency management. For CocoaPods users this issue and solution may not be relevant.
Transitive framework dependency
Let’s say you have three modules: A, B, and C. A depends on B, B depends on C. It means that A depends on C as well, at least indirectly. A is your main module, which is archived and shipped to App Store.
XCode works well with such dependencies, and once your app is successfully compiled, there won't be any missing frameworks in runtime, during development and testing.
But after the build is uploaded and processed by App Store, you are likely to get “amazing” news from App Store Connect, saying that “One or more dynamic libraries that are referenced by your app are not present in the dylib search part”. A little vague, isn’t it?
The first time it took me almost a day to figure out what’s wrong with my build. This is exactly why I decided to write this article in the first place — to save some time for my teammates and other developers.
Invalid bundle
So you go to the App Store Connect and see the following message, which is even less detailed. If you google like a boss, you will find this SO question, which gives you an idea of what’s wrong and how to debug the issue.
A bundle is considered invalid, because all modules, which are used in other modules, but not in the App module, still should be included in the App module. When you have many modules, it’s not that easy to find missing ones.
Missing frameworks
First things first, you need to get the .ipa
file of the troubling build. I have not found an easy way to pull it from App Store Connect. Fortunately, all our builds are stored by the CI. Alternatively, you can get them from XCode.
.ipa
file is an archive, which can be unzipped from terminal by unzip app.ipa -d app
command, where app.ipa
is a name of the archive, and app
is name of directory, to which archive will be unzipped.
Go to Payload folder, and "Show Package Content" for package located there.
In App package, you have all your assets, translations and frameworks, but most importantly The Binary, which have all your source code inside.
To see all used frameworks, type the following command in terminal otool -L app/Payload/App.app/App
, which prints the full list of dependencies.
In parallel, open Frameworks folder, which contains all included frameworks, and find the difference. In my case, it was Foundations.framework
(not to mix up with native Foundation
library), which we extracted and used in other modules, but forgot to include in main App module as direct dependency.
Because Foundations.framework
was listed by otool
, but missing in the Frameworks folder, adding the Foundations.framework
to the App Module solves the bundle issue.
To check if the problem is actually resolved, you need to submit the new build to App Store and wait for its validation. But make sure that all missing frameworks are included this time.
Conclusions
Don't be afraid of “ITMS-90562: Invalid Bundle” email from App Store Connect. It can be resolved in half an hour or so. Or you can preventively include all new iOS modules into your App module.