The app works in debug but crashes in release
“Everything works from Metro or Xcode, but the release build, TestFlight, or Play internal track crashes on launch or on one screen, with a minified or hex-only stack trace.”
ERROR CODES YOU MAY SEE
A code is a clue. Use its meaning and surrounding evidence to narrow the cause.
SIGABRTApple crash reports · platformThe process received an abort signal, typically because it called abort(), for example on an uncaught Objective-C or C++ exception.
Read the language exception reason and Last Exception Backtrace first. Without matching dSYMs the crashing frames stay as hex addresses.
Official reference for SIGABRT (opens in new tab)Code definition reviewedEXC_BAD_ACCESSApple crash reports · platformA bad memory access terminated the process; usually accompanied by SIGSEGV or SIGBUS.
Symbolicate with the dSYM for that exact build before guessing. The faulting address and crashed thread usually point at native code, not JavaScript.
Official reference for EXC_BAD_ACCESS (opens in new tab)Code definition reviewed
THE PRINCIPLE
Never debug an unsymbolicated crash. Archive source maps, mapping.txt, and dSYMs for every build you ship, and test a release build before every submission.
FIRST MOVES
- Reproduce locally with a release build on a device, not only on CI or TestFlight.
- Symbolicate: JS with the matching source map, Android with that build's mapping.txt, iOS with its dSYMs.
- Check build-time config: EXPO_PUBLIC_ variables are inlined only via static process.env.X access and must exist in the EAS or CI environment.
- On Android, ClassNotFoundException or NoSuchMethodException after R8 usually means reflection needs a keep rule.
- Look for dev-only assumptions: code paths guarded by __DEV__ and dependencies declared only for debug (debugImplementation, debug-only pods).
- Upload symbols automatically from CI so Sentry, Crashlytics, App Store Connect, and Play Console show readable traces.
TOOLS: THEN → NOW
PATTERN SNAPSHOT
# JS (Hermes) frames from a release build
npx metro-symbolicate \
android/app/build/generated/sourcemaps/react/release/index.android.bundle.map < trace.txt
# Java/Kotlin frames after R8; mapping.txt is overwritten on rebuild, archive it
$ANDROID_HOME/cmdline-tools/latest/bin/retrace \
app/build/outputs/mapping/release/mapping.txt trace.txt
# iOS crash report with the dSYMs of that exact build available
xcrun crashlog MyApp-2026-10-07.ipsCLOSE THE AI. EXPLAIN THIS.
Why archive the source map, mapping.txt, and dSYMs of the exact build you shipped instead of regenerating them later?HOW IT WORKS UNDERNEATH
RELATED SYMPTOMS
SOURCES
Guide reviewed