On this page
"The app stopped" tells the user nothing and you even less. Logcat, Android's system log, records exactly which exception was thrown, where, and why. Learning to read it is one of the highest-leverage debugging skills you can build.
Find the crash in Logcat
Android Studio's Logcat supports query filters. Useful ones:
package:mine level:error # only your app, errors and above
package:mine tag:OrderRepo # one tag from your app
FATAL EXCEPTION # search for crash headers
is:crash # crashes only (newer Logcat versions)Anatomy of a stack trace
FATAL EXCEPTION: main
Process: com.example.shop, PID: 12345
java.lang.IllegalStateException: Product price missing for id=42
at com.example.shop.cart.CartMapper.toUi(CartMapper.kt:18)
at com.example.shop.cart.CartViewModel$load$1.invokeSuspend(CartViewModel.kt:34)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(...)
at kotlinx.coroutines.DispatchedTask.run(...)
...
Caused by: kotlinx.serialization.MissingFieldException: Field 'price' is required ...
at com.example.shop.api.ProductDto$$serializer.deserialize(...)Common exceptions and their usual fixes
| Exception | Usual cause | Typical fix |
|---|---|---|
NullPointerException | !!, platform types from Java, uninitialised lateinit | Model nullability; safe calls; initialise properly |
IllegalStateException | Invalid state: fragment not attached, checkNotNull failed, ViewModel misuse | Fix lifecycle timing; validate inputs earlier |
NetworkOnMainThreadException | Network call on the main thread | Coroutines + suspend APIs |
IndexOutOfBoundsException | Stale index, list changed | Use stable keys/IDs; getOrNull |
ClassCastException | Wrong type assumption, often from Bundles or reflection | Type-safe navigation arguments; safe casts |
Resources$NotFoundException | Passing an Int value where a resource ID is expected (setText(42)) | Convert to String; check resource qualifiers |
SecurityException | Missing runtime permission | Request permission; check before use |
TransactionTooLargeException | Large Bundle (saved state, intent extras) | Pass IDs; persist large data elsewhere |
From crash to fix: using the debugger
- Click the file link in the stack trace (for example
CartMapper.kt:18) to jump to the line. - Set a breakpoint there, or an exception breakpoint for that exception type (Run โ View Breakpoints).
- Run in debug and reproduce. Inspect variables and the call stack when it stops.
- Write a unit test that reproduces the failing input, fix the code, and watch the test pass.
@Test
fun `product without price is shown as unavailable instead of crashing`() {
val ui = CartMapper.toUi(ProductDto(id = "42", name = "Mug", price = null))
assertEquals("Unavailable", ui.priceText)
}Logging well
private const val TAG = "OrderRepo"
suspend fun placeOrder(order: Order) {
Log.d(TAG, "placeOrder items=${order.items.size} total=${order.totalPaise}") // no personal data
try {
api.place(order.toDto())
} catch (e: IOException) {
Log.w(TAG, "placeOrder failed: network", e) // include the throwable for its stack trace
throw e
}
}- Use levels meaningfully:
dfor debug detail,ifor milestones,wfor recoverable problems,efor failures. - Never log tokens, passwords or personal data.
- Strip verbose logs from release builds (for example with a logging wrapper or Timber's debug tree).
Crashes in production
Logcat only shows your device. For users' crashes, use Android vitals in the Play Console and a crash reporter such as Firebase Crashlytics. Upload R8 mapping files so stack traces are readable (see R8), and add breadcrumbs and custom keys (screen name, feature flag) to reproduce context.
Debugging scenarios
Crash only in release
Usually R8 or reflection. Reproduce with a minified build and add a targeted keep rule.
Crash after returning from background
Usually process death and a missing lateinit or state. Test with "Don't keep activities".
Crash on one manufacturer
Check Android version, permissions behaviour and WebView or OEM differences in vitals breakdowns.
Frequently asked questions
Logcat is too noisy. What can I do?
Filter by package:mine and level, create saved filters, and use consistent tags.
Why don't I see my logs?
Check the selected device and process, the filter, and that your logging isn't stripped in that build variant.
Can AI help read stack traces?
Yes. Tools like Gemini in Android Studio can explain traces and suggest causes, but verify suggestions against the code. See Debugging with AI.
Conclusion
To debug a crash: filter Logcat, read the exception and message, jump to the first frame in your code, check "Caused by", reproduce with breakpoints, and lock in the fix with a regression test. Use Android vitals and Crashlytics for production crashes.
Next step: automate your quality checks with CI/CD for Android with GitHub Actions.
Official references
๐ฑ Apps built by Yunok Tech
Real Android apps on Google Play, free to download.
Walzi4K wallpapers for lock and home screenGet it โธ
NotiVaultNotification history: recover dismissed notificationsGet it โธ
Ready to build real Android applications?
Reading a roadmap is the easy part. The real progress happens when you build a foundation step by step, with someone reviewing your code and answering the questions that come up along the way.
Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.
Explore the Android course and take your next step as an Android developer.