You opened App Store Connect, saw the red Rejected badge, and the reviewer's note said the app crashed on launch under Guideline 2.1, Performance, App Completeness. There is a crash log attached, possibly from a device you do not own, and no other explanation. This is one of the most common rejections in the store, and the fix is almost always smaller than the panic suggests.
Short answer
A Guideline 2.1 crash on launch rejection means the App Review device started your build, hit an unhandled exception before reaching a usable screen, and could not continue. The reviewer attaches the system crash log and quotes a standard line: Apple's App Review Guidelines, section 2.1 state that incomplete binaries that crash will be rejected. The fix path runs through symbolicating that log, reproducing the crash on the same device class the reviewer used, and shipping a new build. There is no penalty for resubmitting once the build launches cleanly.
What you should know
- The crash log is the contract. Apple gives you a
.crashor.ipsfile with the exception type, the failing thread, and stack frames. That is what the reviewer saw. Everything else is interpretation. - iPad is the silent test surface. Many developers test only iPhone, but Apple reviewers frequently launch on iPad Air or iPad Pro. Layout assumptions, multi-window code, and Mac Catalyst paths break here first.
- Distribution signing matters. A build archived with a development certificate runs on your phone, then crashes immediately on a reviewer device because entitlements do not match. The crash log shows a fast SIGKILL with no application frames.
- Backend offline counts as a crash. If your splash screen calls an API, the API returns 500, and your launch path force-unwraps the response, Apple sees a crash. The fix is defensive code, not server uptime.
- Symbolication is required. Without a matching dSYM, Apple's frames are hex addresses. You cannot reason about a stack trace you cannot read.
- Resubmission is free. The 2.1 rejection does not slow your next review. Most developers report a new build clears review within 24 hours in 2026.
What does Guideline 2.1 actually say about crashes?
The short answer is one sentence, and it sits at the end of section 2.1(a). Apple's App Review Guidelines state that submissions should be final versions, that the developer should test on device for bugs and stability before submitting, and that Apple will reject incomplete app bundles and binaries that crash or exhibit obvious technical problems.
That last clause is the lever Apple uses for every crash-on-launch rejection. It does not separate launch crashes from in-session crashes, and it does not give a numeric threshold. In practice, the reviewer pattern is binary: if the build cannot demonstrate its main feature because it crashed first, the build is incomplete by their definition.
This matters because some developers reply to Resolution Center arguing that the crash is rare, edge case, or only on one device. That argument almost never moves a 2.1 decision. The reviewer's test environment is the environment. The expected response is a fixed build.
How do I read the crash log Apple attached?
The log is a plain text or .ips JSON file. Open it in Xcode (drag it into the Devices and Simulators window, or use the Crashes organizer) and Xcode will try to symbolicate against any dSYM bundles you have archived locally.
The parts that matter, in order:
- Exception Type.
EXC_CRASH (SIGABRT)usually means Swift or Objective-C threw and nothing caught it.EXC_BAD_ACCESS (SIGSEGV)means a dereference of a freed or invalid pointer, often a force-unwrapped nil or a use-after-free in an SDK. - Crashed Thread. For launch crashes this is Thread 0, the main thread. If you see Thread 1 or higher, the crash is from a background queue spun up during launch, which narrows where to look.
- Application Specific Information. Often the most useful line. Swift runtime errors print here: "Fatal error: Unexpectedly found nil while unwrapping an Optional value", or "Could not load NIB in bundle".
- Frame above the system frames. Walk down from frame 0. The first frame that names your bundle (not
UIKitCore, notlibobjc, notFoundation) is the line your code died on.
Apple's own guide on symbolicating crash reports is the canonical reference. If your frames stay as hex addresses after Xcode tries to symbolicate, the dSYM for that exact build is missing. Re-download the dSYM from App Store Connect (in the build's TestFlight or Distribution page) or rebuild the archive with bitcode disabled so the dSYM matches the binary App Review ran.
Why does my app launch fine for me but crash for the reviewer?
There are four reproducible reasons, and reading the crash log usually tells you which one.
Reason 1, device class mismatch. Apple reviewers use whatever device is available in their lab. Developer forum threads consistently report iPad Air and iPad Pro as the test devices for iPhone-only submissions. If your storyboard assumes a compact width, your launch screen pins to safe areas you forgot existed, or your initial view controller calls a function that only works on iPhone idiom, the build crashes before the home screen renders.
Reason 2, signing or entitlement mismatch. A build signed with an Apple Development certificate, then uploaded as if it were a distribution build, will crash with a SIGKILL on the reviewer's device because the entitlements do not authorize it for App Store distribution. The fix is to archive with the Apple Distribution certificate and the matching App Store provisioning profile, then re-upload.
Reason 3, network-dependent launch. Your splash screen pings your backend before showing UI. The backend is up for you, geofenced or rate-limited for Apple's corporate network, or returned an unexpected schema. If your launch path force-unwraps the response or calls try! on a decode, the app crashes on the reviewer's network conditions but never on yours.
Reason 4, third-party SDK initialization. An analytics or auth SDK fails to initialize because its config plist is missing from the bundle, an API key is empty in the release config, or the SDK requires a permission you only granted in development. The crash log typically names the SDK's bundle in the top frames.
How do I reproduce the crash before submitting again?
Replicating the reviewer's environment is more important than fixing the first thing that looks suspicious. The closest approximation, in order:
- Install the rejected build directly on a real device through TestFlight. Not your dev build. Not a fresh Xcode build. The exact binary App Review tested, installed through the same delivery channel. The TestFlight build is the binary App Review ran.
- Test on the device class named in the rejection. If the email mentions iPad Air 5th generation on iOS 17.3, find that pair. If you do not own one, Xcode's device simulator with the same iOS version is the next best thing. Several developer reports note that real iPad hardware reveals crashes simulators miss.
- Wipe and reinstall. Delete the app, restart the device, install fresh. App Review starts from a clean state. Cached UserDefaults, Keychain items, or document directory files from your dev sessions can mask crashes that only happen on first launch.
- Throttle the network. Use Network Link Conditioner (in macOS Developer Tools) to simulate a slow 3G profile, or use the iPhone's built-in Developer settings to throttle. Many launch crashes are timeouts that the main thread did not handle.
- Sign out of iCloud, Apple ID, and any in-app account. Reviewers do not have your credentials. If your launch path assumes a logged-in user or an iCloud token, it can crash for them and never for you.
How does the App Store crash review pattern compare to Google Play?
Both stores reject crashes, but the mechanism and the fix path are different.
| Aspect | App Store (Guideline 2.1) | Google Play (Pre-launch report) |
|---|---|---|
| Test surface | Human reviewer plus device farm; iPad common | Automated pre-launch report on physical Firebase Test Lab devices |
| Crash evidence | Single .ips or .crash file in Resolution Center | Multiple stack traces, video, screenshots in Play Console |
| Symbolication | Developer-supplied dSYM matched in Xcode | Native libraries via uploaded debug symbols |
| Fix loop | Resubmit binary, wait for human re-review | Pre-launch report runs automatically on each upload |
| Same-build resubmit | Allowed when network or device-specific | New build almost always required |
| Re-review time | 24 hours typical in 2026 | Pre-launch report finishes in roughly 60 minutes |
The practical difference is that App Review feels more like a verdict and less like a continuous test. You get one snapshot from one device, and you have to triangulate. Google's pre-launch report is noisier but reproducible.
This is also why a calm pre-submission pass matters more on iOS. Some teams run static and dynamic checks before each upload, either with in-house tooling or with platforms that scan the compiled IPA. For builders without the time to run a full crash-reproduction matrix on every release, services like PTKD.com (https://ptkd.com) offer pre-submission scanning aligned with OWASP MASVS and catch a subset of the runtime issues that turn into Guideline 2.1 rejections.
What should I actually change in the binary before resubmitting?
The checklist below maps to the four reproducible causes. Do all four, then submit once.
- Confirm the archive is a release build with the Apple Distribution certificate. In Xcode, Product, Archive, then in the Organizer pick Distribute App, App Store Connect. Do not use ad-hoc, development, or enterprise.
- Verify the dSYM uploads. After upload, App Store Connect should show "Includes Symbols, Yes" for the build. If it says No, your future crash logs from real users will be unreadable too.
- Add defensive launch code. Replace every
try!,as!, and force unwrap on the launch path with guarded variants. The reviewer does not need to see your splash logic, but your splash logic does need to survive a missing or slow response. - Test on iPad. If you submitted as iPhone-only, set the device family to iPhone only in the project settings. If you support both, run on an iPad Air simulator at minimum. Most crash-on-launch rejections on iPad come from a single line assuming a compact size class.
- Confirm backend availability from outside your network. Apple reviewers test on their own network. Use a VPN or a mobile network to confirm your splash endpoints respond.
- Update the build number, not just the version. Apple rejects re-uploads with the same build number. Bump it, archive again, upload again.
What to watch out for
A few patterns get developers stuck in 2.1 loops longer than they should be.
The myth of "same build, just resubmit." Sometimes this works when the crash log clearly shows a transient network failure. Most of the time it does not, and you burn a review cycle. If the stack trace lands in your bundle, you need a new binary.
Replying with screenshots of the working app. Reviewers do not negotiate with screenshots. They re-test. A reply that says "works on my device" without a fix changes nothing.
Assuming Crashlytics will tell you. Crash reporting SDKs only see crashes after their own initialization. If your app crashes during the SDK's setup or before it, Crashlytics is blind. The App Review log is more reliable for launch failures.
Skipping symbol upload. A build without symbols is a build you cannot diagnose. Apple recommends uploading symbols, and TestFlight users will eventually produce crash reports that look just like the reviewer's. Solving symbolication once pays back forever.
Treating 2.1 as a security issue. Guideline 2.1 crashes are quality issues, not OWASP MASTG findings. You can still ship a secure app that crashes on launch. The two passes are separate.
Key takeaways
- Guideline 2.1 with crash on launch means the App Review device hit an unhandled exception before reaching a usable screen, and Apple stops the review there.
- The attached crash log is the only source of truth. Symbolicate it with a matching dSYM, walk the main thread for the first frame in your bundle, and decide whether to ship a new binary or reply in Resolution Center.
- The four causes that produce most rejections are iPad layout assumptions, distribution signing errors, fragile network-dependent launch code, and SDK init failures in release configurations.
- Resubmission is not penalized. Once your build launches cleanly on the device class the reviewer used, the next review is typically quick.
- For teams without time to maintain a full pre-submission test matrix, PTKD.com (https://ptkd.com) is one option for an external scan of the compiled IPA before the next upload, alongside the manual Xcode and TestFlight checks above.
Published 2026-05-17. Last reviewed 2026-05-17.



