FOR REACT NATIVE · EXPO · NATIVE ANDROID & iOS

Find out why your app won’t ship — and fix it before the store tells you.

One command checks signing, SDK levels, privacy manifests, push and login setup, permissions and your build scripts on both platforms. Another one fixes what it can. When a build still fails, paste the log and get the cause and the steps.

$ npx shipdoctor scanSee it run
Free to use · runs on your computer — your code and signing keys never leave it.
React Native 0.88 — fresh from the official template
$ npx shipdoctor scan

ANDROID
  ✖ Release build is signed with the DEBUG keystore
  ✖ applicationId "com.helloworld" is a template default
  ✔ targetSdkVersion 36

IOS
  ✖ Bundle ID is still the React Native template default
  ✖ No DEVELOPMENT_TEAM set on any target
      → Archive will fail with "Signing requires a development team"
  ✖ App icon set is empty (no images in AppIcon)
  ▲ NSLocationWhenInUseUsageDescription is empty

5 errors  2 warnings  3 passed
Real output. Every one of these would block a first release.

Where releases die

GOOGLE PLAY
  • Every upload blocked below target API 36 (since 31 Aug 2026)
  • Native libraries must be 16 KB aligned by 1 Feb 2027 — the warning never says which one
  • Debug-signed bundles, template package names, lost keystores, permission declarations
APPLE APP STORE
  • “Works on my iPhone” — but Archive fails on certificates, profiles and extensions
  • Rejections for privacy manifests, purpose strings, push entitlements and icons
  • Uploads must be built with Xcode 26
BOTH — ESPECIALLY AI-BUILT APPS
  • Thousand-line logs where the real error is near the top
  • AI-written build scripts that work on one Mac and break everywhere else
  • React Native upgrades that break native libraries

Five commands. Real output.

Every screen below was captured from the tool itself.

$ npx shipdoctor scan ./my-app

ANDROID
  ✖ targetSdkVersion 34 — Play requires 36+ since 2026-08-31
  ✖ Release build is signed with the DEBUG keystore
  ▲ Keystore passwords stored in android/gradle.properties

IOS
  ✖ No PrivacyInfo.xcprivacy for the app
  ✖ Missing Info.plist purpose strings:
      NSCameraUsageDescription (react-native-vision-camera)

SCRIPTS
  ✖ build_ios.sh: Windows line endings (CRLF)
  ✖ .github/workflows/ios.yml: iOS build steps on a ubuntu runner
… excerpt

scan — check before you build

Reads your Gradle files, Xcode project, Info.plist, privacy manifest, Podfile, build scripts and CI files. Each problem the stores would reject is listed with its fix. In CI it fails the job, so a broken release never reaches review.

Five days it saves you

GOOGLE PLAY STORE

“I built my app with AI. Google Play rejected my first upload.”

Before: “signed in debug mode”, then “use a different package name”, then “Version code 1 has already been used” — one rejection at a time.

With ShipDoctor: scan lists them all at once. fix --bundle-id sets up release signing and a unique package name, and tells you the one keytool command to run.

XCODE · APPLE

“It runs on my iPhone. Xcode Archive fails.”

Before: running from Xcode uses development signing. An App Store archive needs a distribution certificate, a team on every target and a profile per extension.

With ShipDoctor: fix --team sets the team on every target. log explains certificate/profile errors step by step.

APPLE APP STORE

“App Store Connect rejected my build.”

Before: an email with ITMS-91053 or ITMS-90683 and a guideline number.

With ShipDoctor: scan catches missing privacy manifests and purpose strings before you upload, and fix adds them. Already waiting in review? No tool can speed up Apple’s queue, but you can make sure it doesn’t come back rejected.

GOOGLE PLAY STORE

“Google Play says my update doesn’t support 16 KB pages.”

Before: the warning names no library.

With ShipDoctor: aab names the unaligned .so file, so you upgrade the one dependency that ships it.

BUILD SCRIPTS · CI

“My AI-written build script works on my Mac and breaks in CI.”

Before: “bad interpreter: ^M”, “No such module”, or an iOS job on a Linux runner.

With ShipDoctor: scan checks your .sh and CI files. fix repairs line endings, adds set -e, switches to the .xcworkspace and moves iOS jobs to macOS. Hard-coded passwords are flagged for you to rotate, never silently edited.

Push, logins and permissions — checked, not guessed

These don’t break the build. They break on a real phone: no notifications, a crash on “Sign in with Google”, a silent camera. ShipDoctor reads which libraries you use and checks the config each one needs.

PUSH NOTIFICATIONS
  • google-services.json present and for your package name
  • Google Services Gradle plugin applied
  • POST_NOTIFICATIONS on Android 13+
  • GoogleService-Info.plist in the app target, matching bundle ID
  • Push capability (aps-environment) + background mode — auto-fixed
SOCIAL & PHONE LOGIN
  • Google: REVERSED_CLIENT_ID URL scheme — auto-fixed; SHA-1 / “DEVELOPER_ERROR” check; Play App Signing reminder
  • Facebook: manifest meta-data, strings.xml, Info.plist keys, fb URL scheme — auto-fixed where possible
  • Sign in with Apple entitlement — auto-fixed; Guideline 4.8 warning
  • Firebase phone auth URL scheme
AUDIO · VIDEO · FILES
  • CAMERA / RECORD_AUDIO / location permissions for the libraries you use — auto-fixed
  • Microphone for video, “save to Photos”, background audio on iOS — auto-fixed
  • Old storage permissions limited to Android 12 — auto-fixed
  • Play-restricted permissions (photos/videos, all files, SMS, exact alarms) flagged — the decision stays yours

How it fits your release

  1. 01ScanRun shipdoctor scan in your project folder. Red means the store will reject it.
  2. 02Fixshipdoctor fix shows the changes. --apply makes them, with a backup. Steps that need you (keystore, team ID) are spelled out.
  3. 03Build & verifyBuild the .aab / archive as usual, then run shipdoctor aab on the bundle.
  4. 04Upload — or diagnoseUpload. If anything fails, run shipdoctor log on the output, fix, and go again.
# .github/workflows/release.yml — stop broken releases in CI
- run: npx shipdoctor scan --md shipdoctor-report.md

How it’s tested

Every change runs against real project templates, deliberately broken copies of them, real compiled binaries and real error messages.

357automated checks pass in v0.3 — scan, fix, ipa, config, ci, licensing, payments, logs and support-desk security — plus real-device builds on macOS and Linux
RN 0.88 · Expo 58official templates scanned and fixed to zero errors
58known build & store errors, each tested against a real message
aab · ipareal Android libraries at both alignments; real Apple-signed arm64 binaries, cross-checked with an independent parser

Free to check. $5 when you want it fixed.

Free
$0
  • scan — Android, iOS, push, logins, permissions, scripts & CI
  • aab & ipa — check real builds
  • log — 58 known errors explained
  • deadlines — every store deadline vs your project
  • fix & ci previews — see every change first
$ npx shipdoctor scan
Pro monthly
$5 / month
  • Everything in Free
  • fix --apply — automatic fixes with backup & undo
  • ci --write — working GitHub Actions release workflows for Android & iOS, signed and uploaded
  • --bundle-id, --team, --bump in one command
  • Priority replies to support requests
Get Pro monthly
Pro yearly
$50 / year
  • Everything in Pro
  • Two months free
  • One key for all your projects on your computers
Get Pro yearly

Stuck, or have an idea?

Report a bug, tell us it isn’t working, or ask for a feature. Screenshots and code welcome.

Open support