Skip to content
← BlackLabel Daily
LessonsJune 26, 2026

Six identical rejections and a night on the wrong axes

Michael Barber

All six App Store submissions came back INVALID_BINARY. Not one or two — all six, identically, which should have told me immediately that the cause was environmental, not per-app.

Instead I burned an entire night on the wrong axes. Was it the Xcode version? The iOS SDK point release? The app icon configuration? A premature submission state? A dangling version field? No, no, no, no, and no. Every theory was plausible, every fix was a rebuild-and-resubmit cycle, and every cycle ended the same way: the build would process as VALID, then flip to INVALID_BINARY about thirty seconds after submission.

The actual cause

One field, stamped into every binary, that I had never once looked at: the build-machine OS version. This Mac runs a beta version of macOS. Apple does not accept App Store binaries built on a beta host. Every IPA built here carries the beta fingerprint in its metadata, and the submission pipeline rejects it — deep in processing, after every earlier validation step has happily passed.

That's what made it brutal to diagnose. The local validation tool passed. The upload succeeded. The build processed as VALID. Even the submission API accepted the request. Only the final asynchronous check failed, with error codes that pointed at the SDK and Xcode version — adjacent to the truth, but not it.

What we changed

Two things, immediately:

  • A guard script in the pipeline that refuses to produce App Store builds on this host at all. The failure now happens in one second at build time with a clear message, instead of forty minutes later inside Apple's pipeline with a misleading one.
  • A written diagnosis document, so no future session — human or agent — re-derives this the hard way. The night was expensive; the knowledge shouldn't expire with it.

The fix itself is straightforward in principle: build on a released-macOS machine — another Mac, or a CI runner in the cloud. Getting that lane actually built and proven took another two weeks, and it's a story of its own for a later entry.

The transferable lesson

When six things fail identically, stop debugging the six things. Debug the one thing they share. I knew that rule abstractly and still spent a night violating it, because each individual error message pointed sideways at a per-app cause.

And the deeper habit this reinforced: check the artifact, not the process. The answer was sitting in the binary's own metadata the whole time, one command away. I debugged everything around the artifact except the artifact itself.

Get the next one.

Subscribe to BlackLabel Daily.