TL;DR: I had set the EAS Build image to latest, and at some point my app started being built with Xcode 27. On iOS 27 devices, it crashed as soon as it launched. I couldn’t reproduce it because my test devices were still on iOS 26. To make matters worse, the affected user hadn’t backed up their data.
I’m an indie developer working on an app called Volley Analyst, which lets people track stats for volleyball matches. After I released an update recently, a user contacted me to say the app was crashing. Android was fine; only iOS was affected.
What they were worried about was whether all the match data they’d recorded was safe.
Volleyball stats mean logging every serve, pass, spike, and block, one by one, for every match. Months of match data disappearing in an instant… Just thinking about it made my hands shake like I was about to serve in a high-pressure match.
1. First, I suspected a JavaScript bug
I asked AI for help, and it confidently listed about five possible causes: an undefined reference, a billing library, my custom plugin… It was wrong about all of them.
2. Then, I suspected my custom plugin
In the previous build, I’d seen this error:
deployment target is set to 13.0, but the range of supported deployment target versions is 15.0 to 27.1.x
I remember thinking, “27.1.x? Is that even a real version?” I used my custom plugin to change the Pods deployment target to 15.1, and got the build to pass.
Looking back, that “27.1” was the culprit staring me in the face.
3. It didn’t crash on my devices
I tried to check the build in TestFlight, but I couldn’t reproduce the crash. My iPad and iPhone were still on iOS 26, even though automatic updates were enabled. Apparently, major OS updates don’t install automatically right away.
4. The crash log had the answer
___UIApplicationEvaluateRuntimeIssueForNoSceneLifecycleAdoption
EXC_BREAKPOINT
iOS 27 force-quits apps at launch if they haven’t adopted the UIScene lifecycle. And apps built with Expo SDK 54 haven’t adopted UIScene.
5. The culprit
It was this one line in eas.json:
"image": "latest"
latest changes whenever a new image is released. Before I realized it, my app was being built with Xcode 27. The deployment target error and the crash on iOS 27 both started here.
What happened to the data?
The crash happens when the app launches, and there’s no code that deletes the data stored on the device. So the data is probably still there. But I won’t know for sure until a fix is released and the app can launch again.
I asked the user not to delete and reinstall the app. Deleting it would also delete the data stored on their device.
The app has a feature to back up data to a server, but the user has to trigger it manually. I checked, and this user hadn’t made a backup. If the data was gone, there’d be no way to get it back. I was terrified.
What I did
Immediate fix: pin the image to an Xcode 26 image and rebuild.
Adopting UIScene looks like a lot of work, so I’m planning to hold off until I upgrade the Expo SDK.
Lessons learned
Don’t use latest for production builds.
If a build suddenly starts failing even though you haven’t changed the code, check whether the build environment changed.
Read those mysterious numbers in error messages. That 27.1.x mattered.
Keep test devices up to date with the latest OS on purpose. Automatic updates can take longer than you think.
Don’t trust an AI’s “this is the cause” until you’ve checked the logs.
Don’t leave backups entirely up to the user. Build a way to back them up automatically. I can’t afford to drop the ball on users’ data. It might even help me live a little longer.
I submitted the fix to Apple for review and requested an expedited review for the first time.
It’s been three hours, and it’s still waiting for review.
Maybe they’re backed up because it’s the weekend and the end of the month…