crash-na-testflightblokery-launchutestflight

Aplikacja Expo crashuje na TestFlight: jak to naprawić przed launchem

Praktyczny triage dla aplikacji Expo, które działają lokalnie, a crashują na TestFlight, z regułami decyzji naprawiać czy pisać od nowa.

Paweł Karniej·2 lipca 2026·8 min czytania

Aplikacja Expo działała w preview, przeszła symulator, a padła w momencie, w którym TestFlight zrobił się prawdziwy.

TL;DR

Jeśli aplikacja Expo crashuje na TestFlight, potraktuj to jak awarię buildu release, a nie losowy problem Apple. Typowe przyczyny to brakujące zmienne środowiskowe, natywne moduły, które działały w Expo Go, ale nie weszły poprawnie do buildu, niekompatybilne wersje paczek, zepsuta logika startu, zła inicjalizacja logowania albo płatności, albo wyjątek JavaScriptu, który pojawia się tylko w trybie produkcyjnym. Najpierw ściągnij logi z urządzenia, potem odtwórz problem na buildzie preview albo produkcyjnym z EAS, a dopiero potem zdecyduj, czy naprawiasz jeden bloker, czy przepisujesz kruchy fundament. Jeśli crash siedzi blisko logowania, płatności, onboardingu albo wysyłki do App Store, warto wejść w ustrukturyzowany ratunek zamiast w kolejne prompty.

Najważniejsze fakty

  • Crash na TestFlight oznacza, że aplikacja dotarła do prawdziwego środowiska release na iOS i tam padła.

  • Sukces w Expo Go nie dowodzi, że natywne moduły, produkcyjne zmienne i logika startu w release są poprawne.

  • Pierwszym użytecznym artefaktem jest log z urządzenia albo raport crashu, a nie kolejny domysł na podstawie ostatniej zmiany.

  • Crashe przy starcie zwykle biorą się z logowania, Firebase, Supabase, RevenueCat, deep linków, fontów, splash screena albo brakującej konfiguracji.

  • Napraw crash, zanim zabierzesz się za screenshoty, teksty do App Store i ASO.

  • Przepisz fundament, jeśli wersji zależności, natywnych modułów i stanu startowego nie da się czysto wytłumaczyć.

  • Aplikacje Expo budowane przez AI potrzebują utwardzenia przed TestFlight, zwłaszcza wokół kont, paywalla, analityki i usuwania konta.

Diagnoza: dlaczego build z TestFlight crashuje

Najmocniejsze błędne założenie brzmi: TestFlight zepsuł aplikację. Zwykle nie zepsuł. TestFlight obnażył różnicę między środowiskiem deweloperskim a release.

Expo Go jest hojne. Daje powłokę deweloperską, gotowe natywne moduły, żywe połączenie z Metro i workflow zoptymalizowany pod szybkie iteracje. TestFlight jest odwrotnością. To podpisany build iOS, ze zbundlowanym JavaScriptem, skonfigurowanymi modułami natywnymi, produkcyjną inicjalizacją, zachowaniem trybu release i tymi zmiennymi środowiskowymi, które faktycznie weszły do buildu.

Aplikacja może wyglądać na skończoną w preview, a dalej nie mieć kawałków krytycznych dla launchu:

  • produkcyjnych kluczy API

  • produktów i entitlements w RevenueCat

  • redirect URL-i Supabase

  • wymaganych config plugins

  • wersji paczek kompatybilnych z release

  • obsługi błędów przy starcie

Najczęstszy objaw jest brutalny: aplikacja się otwiera, błyska splash screenem i się zamyka. Czasem wisi na pustym ekranie. Czasem logowanie albo inicjalizacja zakupów zabija aplikację, zanim wyrenderuje się pierwszy ekran.

To nie jest bug UI. To bug gotowości produkcyjnej.

Przy buildach wspieranych przez AI wzorzec jest ostrzejszy. Cursor, Bolt, Replit, Rork i podobne narzędzia szybko generują działające ekrany, ale optymalizują pod następny widoczny błąd. Paczka wchodzi bez sprawdzenia zachowania w release na iOS, Expo dostaje downgrade, żeby uciszyć ostrzeżenie, a kod logowania jest kopiowany po kolejnych ekranach, aż preview zadziała.

Efekt to kod, który potrafi zrobić demo, ale nie przeżyje TestFlight.

Ścieżka naprawy: wyizoluj awarię widoczną tylko w release

Zacznij od logów. Nie zaczynaj od przepisywania ekranu, który akurat pojawił się przed crashem.

  1. Zainstaluj build z TestFlight na fizycznym urządzeniu.

  2. Odtwórz crash od świeżej instalacji.

  3. Ściągnij log z urządzenia z Xcode Organizer, macOS Console albo Twojego zwykłego setupu do debugowania iOS.

  4. Znajdź pierwszy prawdziwy wyjątek, a nie ostatni komunikat z kaskady.

  5. Napraw jedną przyczynę, zbuduj ponownie i przetestuj od czystej instalacji.

Pierwszy wyjątek ma znaczenie, bo późniejsze komunikaty opisują skutki. Na przykład "main has not been registered" pojawia się często po tym, jak wcześniejszy moduł padł przy starcie. Użyteczne pytanie brzmi: który import, która wartość konfiguracji albo który natywny moduł padł, zanim React Native zdążył coś wyrenderować.

Sprawdź najpierw te obszary.

1. Zmienne środowiskowe i konfiguracja produkcyjna

Lokalny development w Expo potrafi ukryć brakującą konfigurację. TestFlight nie potrafi.

Zweryfikuj każdą produkcyjną wartość: bazowy adres API, klucze Supabase, konfigurację Firebase, klucz SDK RevenueCat, endpoint bramki AI, schematy redirect, bundle ID, deep linki i zmienne z profilu buildu EAS.

Jeśli klucz istnieje lokalnie, ale nie ma go w EAS, aplikacja może paść, zanim pokaże cokolwiek sensownego. Kod startowy powinien podczas testów wewnętrznych zawodzić kontrolowanie, z widocznym ekranem błędu, a nie zabijać całą aplikację.

2. Natywne moduły, które Expo Go zamaskowało

Expo Go nie dowodzi, że każda natywna zależność jest obecna w Twoim samodzielnym buildzie. Jeśli dodałeś kamerę, notyfikacje, RevenueCat, obsługę gestów, mapy, zakupy w aplikacji, dostęp do plików albo SDK logowania, sprawdź, czy zależność jest zainstalowana w wersji kompatybilnej z Expo i czy robota z config plugin została wykonana.

Odpal standardowe kontrole zdrowia Expo, potem obejrzyj ostatnio dodane paczki. Jeśli crash pojawił się po zmianie zależności, zakładaj winę warstwy natywnej, dopóki nie udowodnisz czegoś innego.

3. Kod startowy, który robi za dużo

Buildy release karzą kruchy kod startowy.

Złe wzorce startu:

  • inicjalizacja płatności, zanim znany jest stan logowania

  • wywołanie API przy imporcie modułu

  • czytanie secure storage, zanim aplikacja jest gotowa

  • założenie, że obiekt użytkownika istnieje

  • routing przed zakończeniem przywracania sesji

  • rzucanie błędów wewnątrz providerów

Powłoka aplikacji ma być nudna. Wczytuje konfigurację, przywraca sesję, decyduje o pierwszym ekranie i pokazuje kontrolowany stan, jeśli coś padnie.

4. Logika logowania i płatności

Crashe blisko logowania, zakładania konta, restore purchases albo ładowania paywalla są wysokiego ryzyka, bo te przepływy sterują przychodem i gotowością na review.

Logowanie musi odpowiadać, czy użytkownik jest zalogowany, czy sesja jest ważna, czy onboarding jest skończony i co się dzieje po wylogowaniu albo usunięciu konta.

Płatności muszą odpowiadać, czy produkty da się pobrać, czy restore purchases działa, czy sprawdzanie entitlements realnie kontroluje dostęp i czy produkty sandbox i produkcyjne są poprawnie zmapowane.

Jeśli te odpowiedzi są rozsypane po ekranach, nie łataj na ślepo. Potrzebujesz audytu kodu, bo crash jest prawdopodobnie objawem splątanego stanu.

5. Praca pod App Store, która dotyka runtime

Część roboty przed wysyłką zmienia binarium, nie tylko listing. Privacy manifest, uprawnienia, dostawcy logowania, universal links, push notyfikacje i konfiguracja subskrypcji potrafią zmienić zachowanie w release. Napraw crash przed polerowaniem sklepu. Screenshoty nie mają znaczenia, jeśli recenzent nie może otworzyć aplikacji.

Zdecyduj: naprawa czy przepisanie

Reguła: naprawiaj istniejącą aplikację, jeśli awaria jest odizolowana, a ścieżka do launchu zrozumiała. Przepisz fundament, jeśli każda odpowiedź wymaga archeologii.

Naprawiaj, gdy:

  • crash ma jeden jasny wyjątek

  • wersje Expo SDK i React Native są spójne

  • natywne moduły są znane i potrzebne

  • stan logowania ma jedno źródło prawdy

  • logika płatności jest scentralizowana

  • developer potrafi opisać przepływ startu

Przepisz krytyczną ścieżkę, gdy:

  • Expo zostało zdowngradowane albo wymuszone pod jedną paczkę

  • instalacje paczek wymagają flag force

  • to samo sprawdzenie logowania albo entitlement występuje w wielu miejscach

  • buildy release padają po każdej poprawce z innego powodu

  • nie ma jasnego właściciela onboardingu, logowania, dostępu płatnego i stanu nawigacji

  • wymagania App Store nigdy nie były brane pod uwagę przy projektowaniu przepływów

Przepisanie nie oznacza wyrzucenia produktu. Zachowaj zwalidowany pomysł, teksty, ekrany, markę i działający przepływ AI, jeśli są sensowne. Wymień fundament, który blokuje launch.

Ratunek dla aplikacji w Silpho istnieje dokładnie na ten moment decyzji: zaudytować aplikację Expo albo React Native, wskazać prawdziwe blokery i zdecydować, czy naprawiać, przepisać, czy wejść w sprint launchowy.

Porównanie

ŚcieżkaKosztDla kogoRyzyko
Triage logów własnymi siłami0 zł plus Twój czasTechniczni founderzy z czystą aplikacją Expo i jednym jasnym crashemWolno, jeśli pierwszy błąd jest tylko objawem
Kickstart1 990 zł nettoOsoby, które potrzebują boilerplate, sesji 1 na 1, code review i wsparciaMa sens, gdy implementację dalej robisz sam
Audyt Ratunek dla aplikacji1 990 zł nettoAplikacje z AI, gdzie decyzja naprawa kontra przepisanie jest niejasnaAudyt może pokazać, że kodu nie warto zachowywać
Sprint launchowy15 900 zł netto z iOS i AndroidemFounderzy, którzy potrzebują 4 tygodni pracy zrobionej od A do ZZakres musi zmieścić się w sprincie
Launch + Growth23 900 zł netto z iOS i AndroidemAplikacje gotowe na przychód, które potrzebują też materiałów i ASOPrzesada przy jednym odizolowanym crashu

FAQ

Dlaczego moja aplikacja Expo działa lokalnie, a crashuje na TestFlight?

Lokalny development i TestFlight to inne środowiska. TestFlight używa podpisanego buildu release, zbundlowanego JavaScriptu, produkcyjnej konfiguracji i prawdziwego zachowania modułów natywnych. Brakujący klucz, niekompatybilna zależność albo wyjątek przy starcie bywają niewidoczne lokalnie i śmiertelne w release.

Czy aplikacja Expo wygenerowana przez AI przejdzie TestFlight?

Tak, jeśli utwardzisz ją jak produkcyjną. Ryzyko nie leży w tym, że pomagało AI. Ryzyko to brakujące warstwy produkcyjne: stan logowania, płatności, sprawdzanie entitlements, crash reporting, analityka, prywatność, usuwanie konta i testowanie buildu release.

Kiedy przestać łatać crash?

Gdy każda poprawka rodzi nową awarię albo gdy nikt nie potrafi opisać przepływu startu. To zwykle znaczy, że crash nie jest odizolowany. Wtedy robisz ustrukturyzowany audyt i decydujesz o przepisaniu krytycznej ścieżki.

Co naprawić przed ponownym wysłaniem na TestFlight?

Napraw źródłowy crash, potem przetestuj od świeżej instalacji na urządzeniu. Później sprawdź rejestrację, logowanie, wylogowanie, usuwanie konta, ładowanie paywalla, restore purchases, odmowę uprawnień, wolną sieć i główny przepływ AI, jeśli go masz.

Czy wysyłka do App Store wymaga czegoś więcej niż naprawienia crashu?

Tak. Niecrashujący build to dopiero podłoga. Dalej potrzebujesz odpowiedzi o prywatność, usuwania konta, jeśli są konta, informacji o subskrypcji, jeśli sprzedajesz subskrypcje, materiałów do sklepu, linków wsparcia, metadanych i notatek dla recenzenta.

Czy Silpho może naprawić sam crash, bez przepisywania aplikacji?

Czasem tak. Jeśli kod da się uratować, ścieżka ratunkowa ustabilizuje blokery launchu. Jeśli fundament Expo, logowanie, płatności i nawigacja są splątane, przepisanie krytycznej ścieżki jest zwykle krótszą drogą do sklepu.

Następne kroki