Custom Exported Workout missing workoutPlan identifier / Metadata only on the very first app launch/install

Hello everyone,

I am experiencing a strange issue regarding retrieving a custom tracking identifier (workoutPlan identifier) from a custom exported workout that has been imported via HealthKit.

The Issue:

  • First Fresh Install: When the app is installed for the first time and initialized, it fails to load/fetch the workout plan ID from the imported workout.

  • Subsequent Launches / Re-installs: If I close and relaunch the app, the app successfully fetches the workout plan ID from HealthKit with absolutely no problems.

Has anyone found a clean way to handle this without forcing a manual user refresh or an awkward delay/retry mechanism on the first launch?

Any insight, workarounds, or best practices would be greatly appreciated!

Environment: iOS 17+, Swift, HealthKit

I am wondering if that is related to the access authorization. When the issue happened, did you check if your app has the right authorization? Also, is it that you can retrieve the imported workout successfully, but theWorkout.workoutPlan returns nil?

To access the workout data, you need the HealthKit authorization (requestAuthorization(toShare:read:)). I am not sure if the WorkoutKit authorization (requestAuthorization()) is also needed in your case, but it may be worth a try, if theWorkout is valid but theWorkout.workoutPlan is nil.

I am also wondering if that is because HealthKit needs some time to synchronize something with Cloud in the first installation. If that is the case, the issue should go away after the synchronization is done, without the need of re-launching / re-installing the app.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Hi Ziqiao, thanks for the response.

I instrumented this further and can now be precise: it's neither an authorization problem nor a nil return. The await on workout.workoutPlan never returns on the first launch after a fresh install. It doesn't throw and doesn't return nil. The task just hangs indefinitely.

What I verified at the moment of the hang:

  • HealthKit authorization is granted, requestAuthorization(toShare: [], read: [.workoutType()]) completes, and the workout query itself succeeds (I get all my HKWorkout samples back).
  • WorkoutKit authorization is also granted. I read WorkoutScheduler.shared.authorizationState immediately before the plan reads and it reports .authorized.

After a force-quit and relaunch, the exact same code returns the plans immediately. Minimal repro (this is essentially Apple's WWDC23 "Customizing workouts with WorkoutKit" sample extended with a fetch. I reproduced the same hang there too, not just in my production app):

let descriptor = HKSampleQueryDescriptor(
    predicates: [.workout()],
    sortDescriptors: [SortDescriptor(\.endDate, order: .reverse)],
    limit: 25)
let workouts = try await descriptor.result(for: healthStore) // ✅ returns 25 workouts

for workout in workouts {
    let plan = try? await workout.workoutPlan // ⚠️ hangs forever on first launch
    // never reached on first launch
}

Questions:

Is the first-launch hang of HKWorkout.workoutPlan a known issue?

Environment: iOS 17+ deployment target, Swift concurrency, reproduced in the modified Apple sample.

Thanks. That looks like a bug that I am unaware of. Do you have a feedback report yet? If not, would you mind file one and share your report ID here?

It will be even better if you can install the HealthKit profile, follow the guide to capture a sysdiagnose, and attach it to your feedback report. But given the issue can be reproduced with our code, I guess HealthKit folks can do that as well when they investigate the issue.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Custom Exported Workout missing workoutPlan identifier / Metadata only on the very first app launch/install
 
 
Q