Guideline 2.1: Performance — App Completeness
This is the single most common rejection on the App Store. The message in Resolution Center looks like this:
Guideline 2.1 - Performance - App Completeness
We were unable to review your app as it crashed on launch. We have
attached detailed crash logs to help troubleshoot this issue.
Review device: iPhone 16 Pro
OS version: iOS 18.5Or, just as often:
Guideline 2.1 - Performance - App Completeness
We were unable to sign in to review your app. Please provide valid demo
account credentials in App Store Connect so we can review all features
of your app.What guideline 2.1 actually covers
2.1 is not one rule. It's the bucket App Review uses whenever they couldn't finish reviewing your app. The cause is almost always one of five things:
| Trigger | What the reviewer saw |
|---|---|
| Crash on launch or during review | The app quit, usually on a device or OS version you didn't test |
| Demo account missing or broken | A login wall they couldn't get past |
| Placeholder content | Lorem ipsum, "Coming soon", a stub screen, a TODO in the UI |
| Dead links | Support URL, privacy policy, or an in-app link returning a 404 |
| Backend unavailable | Your staging server was off, or the API rejected their region/IP |
The common thread: the reviewer could not exercise the app end to end. Nothing here is a judgment call about your idea. Every one of these is mechanical, and every one is preventable.
Crash on launch
The single biggest cause, and the most frustrating, because it usually works fine on your machine.
- Reviewers test on current hardware running the current OS, often a beta. Build against the latest SDK and run on the newest simulator before you archive.
- They test on a fresh install with no data. Your app may depend on state that only exists because you've been running it for months. Delete the app, reinstall, launch — that's the reviewer's first run.
- They test on a network you don't control. Reviews are frequently done from mainland China; if your app hard-fails when a request times out, or when a service that's blocked there doesn't respond, it crashes for them and works for you.
- A missing
NS…UsageDescriptionpurpose string is a guaranteed crash the first time the gated API is called. See ITMS-90683.
The crash log is attached to the rejection in Resolution Center. Symbolicate it — don't guess.
The demo account
If any screen requires sign-in, you must supply working credentials in App Store Connect ▸ your version ▸ App Review Information, with Sign-in required checked.
Where these go wrong:
- The account expired. Trial accounts, seats deactivated after 30 days, passwords rotated between submission and review. The account has to work for the entire review window, and for every resubmission after that.
- Two-factor authentication. The reviewer cannot receive your SMS or your authenticator code. Either exempt the demo account from 2FA, or explain in the review notes exactly how to bypass it.
- The account has no data. An empty account shows the reviewer an empty app. Seed it so every feature is reachable.
- Region locking. If your backend geofences and the reviewer is outside your launch region, they see nothing. Whitelist the demo account.
Use the Notes field for anything non-obvious: how to reach a feature that's behind a paywall, what a sandbox purchase does, why a section is empty on a first run. Notes cost you five minutes and remove entire classes of rejection.
Placeholder content and dead links
Search your project before you archive:
sh
grep -rn "lorem\|Lorem\|TODO\|Coming soon\|placeholder" --include="*.swift" --include="*.strings" .Then open every URL your listing points at — support URL, marketing URL, privacy policy — in a private window. A support page behind a login, a domain that expired, or a page that 404s is a 2.1 rejection on its own.
Fixing it and resubmitting
2.1 is a metadata-and-binary mix, so the fix depends on the cause:
- Crash or placeholder content — needs a new build. Fix, bump the build number, re-archive, upload.
- Demo account or notes — no new build needed. Edit App Review Information, reply in Resolution Center, and resubmit the same build.
Reply in Resolution Center either way. Tell the reviewer what you changed; a resubmission with no explanation goes back into the same queue with the same reviewer assumptions.
Catching it before you submit
Three of the five triggers are visible without building anything — they're fields in App Store Connect that are either filled in or not. That's exactly what AuditStore reads:
demo-account— flags a version that declares sign-in is required but ships no credentials.review-contact— flags missing contact name, phone, or email, so the reviewer can actually reach you.review-notes— flags an empty notes field.support-url— issues a realHEADrequest and flags a support URL that doesn't respond.usage-strings— flags the missing purpose string that would crash the app on the reviewer's device.
The App Store Connect checks need an API key; the project checks run locally with no credentials at all.
Related
- ITMS-90683: Missing purpose string — the crash-on-launch cause you can catch statically
- App Review checks — contact, notes, demo account
- Guideline 2.3: Accurate Metadata