"Invalid Binary": no reviewer, no message, and how to find the real reason
Invalid Binary is a processing failure, not a rejection. No reviewer saw your app. Apple's delivery pipeline unpacked the build, checked it against its structural rules, and refused it. Your listing, screenshots and metadata are irrelevant to it and are not at fault.
The state value is INVALID_BINARY, and there is no Resolution Center message, because Resolution Center is for conversations with reviewers and there is no reviewer here.
That absence is the whole problem. A rejection comes with an explanation attached to it. Invalid Binary frequently comes with nothing at all.
Why the reason goes missing
Three separate things have to happen for you to find out why, and any one of them failing leaves you with a bare state and no cause.
The check runs server-side, after the upload finishes. Xcode's local validation runs a subset of the rules. It can pass cleanly and the full server-side check can still refuse the build. So "but it validated" is not evidence of anything.
The reason arrives by email, not in the console. The ITMS codes that explain the refusal are emailed to particular roles on the developer account. If you are not on that list, or the address is a shared inbox nobody reads, or the mail landed in spam, the explanation exists and you never see it.
Sometimes no email is sent. Developers have reported the state changing with no notification at all, going back years. There is no mechanism to request the message after the fact.
Where to look, in order
Work down this list. It is ordered by how often each step finds the answer, not by how easy it is.
1. The right email account. Find out which role on your developer account receives delivery notifications, and check that inbox including spam. On small teams the account holder is often not the person doing the uploading, and the explanation has been sitting in their mail for two days.
2. The build's own row in App Store Connect. Open TestFlight or the build list for the app and find the build. An invalid build is usually marked as such there, and sometimes carries a short reason next to it. This is faster than it sounds and people skip it because they are looking at the version page instead of the build page.
3. Xcode's Organizer. Select the archive and look at the distribution logs. Xcode keeps the delivery output, including whatever the transporter said on its way out.
4. Re-run the upload through the Transporter app. This is the highest-value step and the least used. Apple's standalone Transporter app prints the full ITMS output where Xcode sometimes summarises it away. Same binary, same pipeline, more words. Every upload route ends up in iTMSTransporter underneath, so you are not changing the outcome, only the verbosity.
5. Validate before uploading next time. xcrun altool --validate-app runs the pre-flight check and prints its findings. It will not catch everything the server catches, but it turns some of these into a failure you see in your terminal instead of a state you discover an hour later.
6. Bump the build number and upload again. Last resort, and bounded: once. Some of these clear on a fresh upload with no change to the binary, which means Apple's side had a bad moment. Twice on two builds is not a bad moment, it is your build.
You cannot reuse a build number. Every upload attempt consumes one, so bump CFBundleVersion before each retry. The version string stays where it is.
What actually causes it
Once you find the ITMS code, it will be one of a familiar set. The common groups:
- Signing and provisioning. An ad hoc or development identity where a distribution one was needed, an expired certificate, a profile whose entitlements no longer match the App ID, or an unsigned framework inside the bundle.
- Bundle structure. A framework embedded twice, a stray static library copied in as a resource, a nested
Frameworksfolder inside an embedded framework, an.appexin the wrong directory. - Missing icons. No 1024 by 1024 icon in the asset catalogue, or a gap in the required sizes. Uploading the marketing icon in App Store Connect does not satisfy the binary check.
- Info.plist problems. A missing
CFBundleVersionorCFBundleShortVersionString, often on an extension rather than the app. A version string that is not higher than the last approved one. - Architectures. Simulator slices left in a vendor framework, or an architecture set that does not match your declared device capabilities.
- Toolchain. A beta Xcode, or an SDK below Apple's current floor.
- Privacy. A missing privacy manifest for a required-reason API, or a third-party SDK without its own manifest or signature.
Each of these has a code, and the code names the file. That is why steps 1 to 4 above matter so much more than guessing from this list.
What it is not
Three states get confused with this one and none of them are fixed the same way.
REJECTED means a human reviewed your app and objected to it. There is a message in Resolution Center. Read it.
METADATA_REJECTED means a human objected to your text or screenshots. No new build required at all.
Missing Compliance means the build is fine and you have not answered the export compliance questions. The build sits there, usable in TestFlight, unable to be submitted, until you answer them or set ITSAppUsesNonExemptEncryption in your Info.plist. It looks like a blocked build and it is a form you have not filled in.
If you are staring at INVALID_BINARY and looking for the guideline you breached, stop. There is no guideline. It is a file format problem.
After you fix it
The version record is untouched by any of this. You are replacing a build, not restarting a release:
- Fix whatever the code named.
- Bump the build number.
- Upload.
- Wait for processing to complete.
- Attach the new build to the same version.
- Submit.
The version string does not change and the metadata you already pushed is still there. An Invalid Binary costs you an upload and a processing wait, and nothing else.
The part worth changing about your process
The reason this error is expensive is not the fix. Most of these are a build setting. It is expensive because the explanation is somewhere you were not looking, and the state gives you nothing to go on.
So: find out today which email address receives Apple's delivery notices, and make sure a human reads it. That one piece of housekeeping removes most of the cost of this error before you next hit it.
AppSubmit keeps the full transporter output on the release timeline and will not call a delivery successful without it, precisely because a state with no reason attached is the failure mode this error is famous for. Running the upload through Apple's Transporter app yourself gets you the same text.