App Store Review Guidelines
Common rejection reasons for Expo apps in 2026 - a cookbook for passing automated upload checks and human App Review when shipping React Native binaries built with EAS, not Expo Go.
Search across all documentation pages
Common rejection reasons for Expo apps in 2026 - a cookbook for passing automated upload checks and human App Review when shipping React Native binaries built with EAS, not Expo Go.
Quick-reference recipe card - copy-paste ready.
# Pre-submission gate (run on every release branch)
npx expo-doctor
npm audit --audit-level=high
eas build --profile production --platform ios
# Install Release-equivalent build on device before submit
eas build --profile preview --platform ios # internal distribution
# Dogfood: cold start, login, paywall, push tap, universal link, logout + delete account
# Submit with metadata from repo (not from memory)
eas submit --platform ios --latest
# Privacy manifest sanity - after prebuild
plutil -p ios/ShopApp/PrivacyInfo.xcprivacy 2>/dev/null || \
grep -r NSPrivacyAccessedAPIType ios/// app.config.ts - rejection preventers bundled together
export default {
expo: {
ios: {
bundleIdentifier: "com.example.shopapp",
privacyManifests: {
NSPrivacyAccessedAPITypes: [
{
NSPrivacyAccessedAPIType: "NSPrivacyAccessedAPICategoryUserDefaults",
NSPrivacyAccessedAPITypeReasons: ["CA92.1"],
},
],
},
infoPlist: {
NSCameraUsageDescription: "ShopApp uses the camera to scan product barcodes.",
NSPhotoLibraryUsageDescription: "ShopApp lets you choose photos for your profile.",
},
},
plugins: ["expo-apple-authentication", "expo-notifications"],
},
};When to reach for this:
eas submit.Symptom: Upload or TestFlight processing fails within minutes; email lists NSPrivacyAccessedAPICategory* APIs without approved reasons.
Fix:
npx expo install --fix - Expo SDK packages ship PrivacyInfo.xcprivacy files.ios.privacyManifests - see iOS Privacy Manifests.ios: {
privacyManifests: {
NSPrivacyAccessedAPITypes: [
{
NSPrivacyAccessedAPIType: "NSPrivacyAccessedAPICategoryFileTimestamp",
NSPrivacyAccessedAPITypeReasons: ["C617.1"],
},
],
},
},Symptom: "App offers Google login but not Sign in with Apple."
Fix: Add expo-apple-authentication when offering Google/Facebook/email-password account creation. Login-only apps without third-party auth may be exempt - document in Review notes.
Symptom: "Users can create accounts but cannot delete them in the app."
Fix: Settings → Delete Account → confirm → call backend delete API. Link to web deletion is not sufficient if the app supports in-app registration.
// Settings screen pattern - must actually delete server-side account
async function deleteAccount() {
await api.delete("/me");
await signOut();
router.replace("/welcome");
}Symptom: Reviewer cannot log in, hits white screen, or demo account fails.
Fix checklist:
| Item | Pass criteria |
|---|---|
| Demo account | Active credentials in App Store Connect → App Review Information |
| Release build | Test eas build --profile production, not Metro Debug |
| ATT / permissions | First-launch flows completable without dead ends |
| Offline | App does not crash on airplane mode at splash |
| Universal links | Marketing URL opens app - iOS Universal Links |
Symptom: "App is primarily a website wrapper" or "duplicate of existing apps without differentiation."
Fix:
Symptom: Declared audio, location, or fetch background modes without feature; privacy label mismatch.
Fix:
UIBackgroundModes from infoPlist.expo-updates, Sentry, Amplitude, etc.).What this demonstrates:
| Code / theme | Typical Expo cause | Prevention |
|---|---|---|
| ITMS-91053 | SDK uses UserDefaults, disk space, boot time APIs | privacyManifests + expo install --fix |
| 2.1 Performance | Hermes crash, missing native module in Release, bad OTA | Production profile QA; feature flags off broken screens |
| 4.2 Design | WebView shell, template clone | Native UX, offline, platform value |
| 4.8 Login | Google without Apple | expo-apple-authentication |
| 5.1.1 Privacy | Missing deletion, vague policy, ATT without NSUserTrackingUsageDescription | In-app delete; accurate labels |
| 2.3.3 Screenshots | Expo Go UI in screenshots | Capture from production build |
| 3.1.1 IAP | Digital goods via Stripe only | StoreKit for consumables/subscriptions |
| 2.5.4 Background | Copy-paste UIBackgroundModes | Only modes you implement |
| 5.4 VPN / MDM | Enterprise APIs without entitlement | Remove unused entitlements |
Fill every field in App Store Connect before submit:
Sign-in required: Yes
User name: review@example.com
Password: <rotating demo password>
Notes: Tap "Browse as guest" on login to skip auth. Push notifications require
physical device - universal links tested at https://shop.example.com/orders/demo.
Account deletion: Settings → Account → Delete Account.Expo apps use HTTPS (standard encryption). In Connect:
ITSAppUsesNonExemptEncryption = false in infoPlist avoids annual paperwork for typical apps.
expo-tracking-transparency + NSUserTrackingUsageDescription before any tracking SDK initializes.expo-dev-menu visible. Fix: production profile without developmentClient: true.supportsTablet: true. Fix: 13" iPad screenshots or disable tablet support intentionally.appID - not "works on simulator only.""Allow $(PRODUCT_NAME) to access camera" left as TODO. Fix: human-readable product-specific copy.| Alternative | Use When | Don't Use When |
|---|---|---|
| TestFlight external first | Soften risk before public App Store | Simple bugfix - internal may suffice |
App Store Connect API + eas submit | Repeatable CI releases | One-off - manual upload OK |
| Phased release (7-day) | Limit blast radius | Hotfix needed immediately worldwide |
| Enterprise distribution | Employee-only apps | Consumer App Store product |
Stack versions: This page was written for React 19.2.3, React Native 0.86.0, and Expo SDK 57 (
expo~57.0.4).
Reviewed by Chris St. John·Last updated Jul 16, 2026