Why an app crashes is written down somewhere, and the crash log is not in the same place on iOS and Android.
The log is already on the phone. On an iPhone it is at Settings, then Privacy and Security, then Analytics and Improvements, then Analytics Data, named after your app's binary. On Android it is inside a bug report: the tester opens Developer options and taps Take bug report, or you connect the phone and run adb bugreport. Both paths come from Apple's and Google's own developer documentation, opened on 3 October 2026.
Most readers here have a crash on a tester's phone, not in a simulator, so that is the reader this is written for. It covers where each platform puts the log, what the owner of the phone has to agree to first, what their refusal costs you, and the four crash types Apple says never reach its dashboard at all. If the app is slow rather than dead, that is app performance and a different question.
Find where your log isThe short version
A mobile crash is a file on hardware you do not own and the person holding it decides whether you see it.
That is the whole difference from a server crash. Apple's Crashes organizer only shows reports from customers who share diagnostic and usage information. Google says Play Console crash data comes from devices whose users opted in to automatically share their usage and diagnostics data. Neither platform asks your app for permission, and neither gives your code a prompt it can show. The consent is a system setting, made long before that person installed anything of yours.
There is one exception, and it is worth the whole page. Apple's documentation states that TestFlight users of your app automatically share crash reports with you, regardless of the device settings for sharing diagnostic and use data. Android has no equivalent: a bug report is something the tester has to go and take. So for a test group, Android is plainly the harder platform. For one phone you can plug a cable into, Android is the easier one, because the Android Debug Bridge hands you everything and asks nobody's permission.
Where the crash log lives on each platform
On iOS, iPadOS, tvOS, visionOS and watchOS the device writes the report itself, and Apple's instructions are five taps. Open the Analytics and Improvements section of Settings, tap Analytics Data, find the log, then use the share icon and pick Mail. The name tells you what you are holding: a crash report is your app's binary name followed by the date and time, and a kill caused by high memory use is JetsamEvent followed by the date and time. Reports from a watchOS app are on the paired iPhone. Crash reports carry a .crash or a .ips extension, and when you have both Apple says to share the .ips.
On Android nothing is sitting in Settings for the user to find. The logging system is a set of circular buffers kept by the system process logd, and the one you want is called crash. Live, you read it with the Logcat window in Android Studio or with adb logcat -b crash from a shell. After the fact you want a bug report, which bundles the logcat output with diagnostic output for system services from dumpsys and the dumpstate error logs. Reports already taken sit on the device at /bugreports as bugreport-BUILD_ID-DATE.zip, with the stack traces in the matching .txt file.
The word circular is the part that bites. The crash buffer is a ring, so a chatty device overwrites your crash while you are still writing the email asking for it. Native crashes are worse: Google's reference notes that tombstone traces live in a separate global circular buffer and may be overwritten by newer crashes, including crashes from other applications, so the call that fetches one can return null. Ask an Android tester for the bug report the same day.
Try it
Where your crash log is right now
Which phone
Where it crashed
Pick a phone and a situation. Every answer is a path read out of Apple's or Google's own documentation on 3 October 2026, not out of a tutorial.
A crash on a tester's phone is not the same job as a crash in a simulator
Start with why you cannot just attach a debugger. Apple states it plainly: distribution builds of an app, including builds for a testing team, do not contain the entitlements needed for debugging in Xcode. The build your tester installed is not debuggable by design, so crash reports and device logs are the only instrument you have. The flip side is the good news: TestFlight and the App Store collect crash reports for every submitted version of your app, and TestFlight testers share theirs automatically.
There is a matching trap the other way. When your app crashes while you run it from Xcode, the debugger intercepts the crash so you can inspect state, which means the operating system never writes a report. If you want the file, detach first: Debug then Detach, or the detach command in the console. People spend afternoons hunting a crash log that was never created because the debugger ate the crash.
A simulator also cannot produce several of the terminations that hurt most in the field. Apple lists four kinds that never appear in the Crashes organizer and have to be collected from the device by hand: watchdog events such as a launch that took too long, invalid code signature crashes, thermal events where the device overheats because an app uses too much CPU, and jetsam events where an app uses too much memory. A Mac neither runs out of memory the way a phone does nor throttles like one, so a real device pass belongs inside app testing before launch, not after it.
Apple Developer, Acquiring crash reports and diagnostic logs, read 3 October 2026
What the owner of the phone has to agree to, and what their refusal costs
Neither platform has a permission your app can request for this. There is no key you add to Info.plist and no runtime dialog, because the crash log is written by the operating system about your process, not collected by your code. On iOS the switch is Settings, Privacy and Security, Analytics or Analytics and Improvements, then Share iPhone and Watch Analytics. On Android it is the device setting for automatically sharing usage and diagnostics data. Both are system wide, and whoever declines has declined for every developer at once.
What a refusal costs is specific, not total. On iOS you lose that person from the Crashes organizer and keep your whole TestFlight group, because Apple exempts TestFlight from the setting. On Android you lose them from Android vitals, under Monitor and improve in Play Console, where crash and ANR data is limited to opted in devices and goes back six months. Neither refusal removes the file from the device, so a cooperative user is always a route in. Google is blunt about how pleasant that route is: bug reports are useful while you are using the app yourself, but your end users cannot easily share them with you.
Declaring the data is a separate obligation, and it starts when you add a crash reporting SDK of your own. Apple's app privacy categories include a Diagnostics group with Crash Data, described as crash logs, declared in App Store Connect. Google Play's Data safety form has Crash logs under App info and performance, defined as crash log data from your app, for example stack traces or the number of times your app has crashed. Reading the platform's own reports needs no declaration. Shipping your own reporter does, and keeping that disclosure true is part of app maintenance rather than a one off at launch. One related precision, because the wrong version is everywhere: reading your own app's exit history needs no permission, and reading another package's needs android.permission.DUMP, which a normal app will not get.
Android Developers, Capture and read bug reports, read 3 October 2026
The in app APIs changed names, and the old ones are what older pages describe
If you want the crash inside your own code rather than in a console, both platforms hand it to you, and on both the API people blog about is the previous one. On Apple platforms the framework is MetricKit. In iOS 27 and later and macOS 27 and later a MetricManager instance delivers diagnostic reports through an asynchronous sequence you iterate with for await. Before that you used the shared MXMetricManager, added an object conforming to MXMetricManagerSubscriber, and received an MXDiagnosticPayload holding MXCrashDiagnostic values. Diagnostic reports arrive immediately in iOS 15 and later; earlier they waited for the daily metric delivery.
On Android the equivalent is ActivityManager.getHistoricalProcessExitReasons, which returns ApplicationExitInfo records most recent first. Both arrived in API level 30. The reason codes are the useful part: REASON_CRASH for an unhandled Java or Kotlin exception, REASON_CRASH_NATIVE for a native crash, and separate codes for an ANR, a low memory kill and a user initiated force stop. That is how you finally tell a crash apart from the system reclaiming your process. From Android 12, API level 31, getTraceInputStream returns the native tombstone as a protocol buffer; Google notes that previously the only way to get it was through the Android Debug Bridge.
Two limits before you build on any of this. The exit history is a ring buffer and only the most recent records come back, and Android's documentation does not publish how many records the system keeps per app, so do not design around a number you read somewhere. And a trace full of hexadecimal addresses is not a bug report yet: Apple's reports need symbolicating against the archive you kept when you shipped, and Android native frames need a debug symbols file uploaded to Play Console, or ndk-stack locally.
All of it tells you that one process died once. None of it tells you the crash only hits one Android version, or only first launch after an update, or only new users. Those are patterns across sessions, which means seeing it happen to real users rather than reading one file very carefully.
Where to look, and who has to agree before you can
| What you have | iOS | Android | Who has to act first |
|---|---|---|---|
| Your own run from the IDE | Xcode debugger holds it; Debug then Detach to get a real report | Logcat window, or adb logcat -b crash | Nobody |
| A build you sent to testers | Crashes organizer, TestFlight reports shared automatically | Developer options, Take bug report, then share the notification | Nobody on iOS; the tester on Android |
| The phone on your desk | Devices and Simulators window in Xcode | adb bugreport, or adb pull from /bugreports | You, with a cable |
| The raw file on the device | Settings, Privacy and Security, Analytics and Improvements, Analytics Data | /bugreports as bugreport-BUILD_ID-DATE.zip | The owner emails or shares it |
| A public release | Crashes organizer, no watchdog, thermal, jetsam or code signature crashes | Play Console, Android vitals, Crashes and ANRs, last six months | The user opted into sharing diagnostics |
None of this changes because an agent wrote the code
The crash log is written by the operating system about your process, so the file is the same whether you typed every line or described the app in a sentence. A React Native stack trace arrives through the two doors above either way. What changes is how fast you can get a build onto a real phone, because that is the only place the interesting terminations happen.
Newly is an AI app builder. You describe the app and it writes a real React Native and TypeScript project you own, runs it on cloud iOS and Android simulators while it builds, then uploads to TestFlight and publishes to Google Play internal testing. It is $25 a month and there is no free plan. Two things follow for crash work: your iOS testers are TestFlight testers, so Apple hands you their crash reports with nothing to configure, and you hold the project, so a symbolicated trace points at your own files. Take the code out as a ZIP from project Settings, or through the two way GitHub sync under Deploy, when you want a debugger attached locally.
The honest limit: a cloud simulator is still a simulator. It will not produce a jetsam event, a thermal event or a watchdog termination, and it will not tell you the app crashes on launch on a three year old mid range phone with no free storage. Get the build onto real hardware, and onto somebody else's real hardware, before a green simulator run counts as a result.
Questions people ask when an app crashes
Because a simulator has the Mac's memory, the Mac's storage and no thermal limit. Apple lists four crash types that never appear in its Crashes organizer and have to be collected from a device: watchdog events such as a launch that took too long, invalid code signature crashes, thermal events, and jetsam events caused by high memory use. The first and the last are the usual explanation for a crash that only happens on real hardware. A distribution build is also not debuggable in Xcode, so you need the device log rather than a breakpoint.
Describe the app, then get it onto a real phone
Write the feature down in plain English, ship the build to TestFlight and to Google Play internal testing, and read your first crash log off a device instead of a simulator.
Start building