Description
After upgrading from @kingstinct/react-native-healthkit@12.1.2 to @14.0.0 (then 14.0.1), the HealthKit permission/access sheet briefly appears (slide-up 95% screen) and is immediately dismissed by iOS on every cold start of the app, even though the user previously granted permissions during onboarding.
The sheet appears even though our JS code does not call requestAuthorization at cold start — we only call read queries (getMostRecentQuantitySample, queryStatisticsForQuantity, queryWorkoutSamples).
This did not happen with 12.1.2 (last known good version we had pinned). Downgrading to 13.4.0 resolves the issue.
Environment
@kingstinct/react-native-healthkit: 14.0.1 (also reproduced on 14.0.0)
react-native-nitro-modules: 0.35.6
- React Native:
0.83
- Expo SDK:
55
- iOS: 18.x on physical device
- App user has
weight.read = granted, weight.write = granted, activity.read = denied (relevant: user denied activity access during onboarding)
Reproduction
- App user grants weight read/write but denies activity read during onboarding.
- Cold start the app (kill from multitasker, relaunch).
- ~2.5–3.5 seconds after the home screen appears (we call sync after a deferred delay for startup perf), a sheet-style modal slides up from bottom (95% screen, blank/white) and is immediately dismissed by iOS.
- JS-side, our calls (
getPermissionsStatus, getMostRecentQuantitySample, queryStatisticsForQuantity, queryWorkoutSamples) all return quickly (1–200 ms total) without errors — so the sheet appears asynchronously to our JS, triggered by the native side.
Suspected cause
We suspect the 390f784 patch in v14.0.0 ("register observer queries in AppDelegate for background delivery") or the new typed-metadata API introduced in v14.0.0 triggers an implicit re-validation of permissions on first data access after a cold start — specifically when the app reads/queries types where the user previously denied access (in our case HKQuantityTypeIdentifierStepCount, HKQuantityTypeIdentifierActiveEnergyBurned, etc.).
In v12/v13, queries on denied types appeared to return empty silently. In v14, iOS now seems to present the HealthKit access sheet automatically — but since the user has already responded (denied), iOS dismisses it instantly. The visible flash is the UX bug.
What we tried
- Disabling our cold-start
setTimeout(syncHealth, 2500) → modal disappears. So the trigger is one of our query calls (not the AppDelegate observer setup alone).
- Isolating individual calls: didn't fully isolate before reverting (
syncFromAppleHealth ~192 ms / syncActivityForDay ~64 ms — both are candidates).
- Reverting
@kingstinct/react-native-healthkit to 13.4.0 (keeping react-native-nitro-modules@0.35.6) → modal disappears.
Workaround
Pin @kingstinct/react-native-healthkit to 13.4.0 until this is resolved.
Questions
- Is this an intended behavior change in v14 (re-validate permissions on first access per session)?
- If so, is there an opt-out or a way to query "silently" for denied types without triggering the sheet?
- Otherwise this looks like a UX regression worth fixing in v14.x.
Thanks!
Description
After upgrading from
@kingstinct/react-native-healthkit@12.1.2to@14.0.0(then14.0.1), the HealthKit permission/access sheet briefly appears (slide-up 95% screen) and is immediately dismissed by iOS on every cold start of the app, even though the user previously granted permissions during onboarding.The sheet appears even though our JS code does not call
requestAuthorizationat cold start — we only call read queries (getMostRecentQuantitySample,queryStatisticsForQuantity,queryWorkoutSamples).This did not happen with
12.1.2(last known good version we had pinned). Downgrading to13.4.0resolves the issue.Environment
@kingstinct/react-native-healthkit:14.0.1(also reproduced on14.0.0)react-native-nitro-modules:0.35.60.8355weight.read = granted,weight.write = granted,activity.read = denied(relevant: user denied activity access during onboarding)Reproduction
getPermissionsStatus,getMostRecentQuantitySample,queryStatisticsForQuantity,queryWorkoutSamples) all return quickly (1–200 ms total) without errors — so the sheet appears asynchronously to our JS, triggered by the native side.Suspected cause
We suspect the
390f784patch in v14.0.0 ("register observer queries in AppDelegate for background delivery") or the new typed-metadata API introduced in v14.0.0 triggers an implicit re-validation of permissions on first data access after a cold start — specifically when the app reads/queries types where the user previously denied access (in our caseHKQuantityTypeIdentifierStepCount,HKQuantityTypeIdentifierActiveEnergyBurned, etc.).In v12/v13, queries on denied types appeared to return empty silently. In v14, iOS now seems to present the HealthKit access sheet automatically — but since the user has already responded (denied), iOS dismisses it instantly. The visible flash is the UX bug.
What we tried
setTimeout(syncHealth, 2500)→ modal disappears. So the trigger is one of our query calls (not the AppDelegate observer setup alone).syncFromAppleHealth~192 ms /syncActivityForDay~64 ms — both are candidates).@kingstinct/react-native-healthkitto13.4.0(keepingreact-native-nitro-modules@0.35.6) → modal disappears.Workaround
Pin
@kingstinct/react-native-healthkitto13.4.0until this is resolved.Questions
Thanks!