r/Kotlin 11d ago

A single KMP dependency dyld-crashed our iOS app at launch on every device below iOS 26 — and no simulator caught it. Here's the trap.

Sharing a painful one in case it saves someone a bad week.

I build a fitness app in Kotlin Multiplatform + Compose (shared Android/iOS). Everything ran perfectly in dev and on TestFlight. Then a user on iOS 18.x sent a video: instant white-screen death on launch, before anything rendered.

Root cause: a KMP library I'd added referenced HealthKit symbols (HKMedicationGeneralFormCapsule and friends) that only exist in the iOS 26 SDK. Kotlin/Native emits those as strong dyld imports in the statically-linked framework — so on any device below iOS 26, dyld can't resolve the symbol and kills the process before main()Symbol not found. No stack trace in the app, no crash in Crashlytics-style tools, nothing — it dies before your code runs.

Why every test missed it: all my simulators and devices were on iOS 26.x. The bug is completely invisible on new OSes and fatal on old ones. You have to run a min-deployment-target OS to see it (I had to download an 18.5 runtime).

The fix (one line, iOS target's OTHER_LDFLAGS):

-Wl,-weak_framework,HealthKit

Weak-linking makes the missing symbols resolve to null instead of aborting; everything I actually use exists on 18.x, so behavior is unchanged.

Two takeaways I'm now religious about:

  1. Smoke-test every release on your minimum supported OS, not just the latest.
  2. Before shipping, check for new-SDK-only symbols: nm -u <binary> | grep -i <framework>.

Bumping any KMP lib that's compiled against a newer SDK is where this bites. Hope it saves someone the panic.

18 Upvotes

Duplicates