Skip to content

Setup troubleshooting

The failures that show up on a first integration, and what each one actually means. For a failure that reached your catch block with a code attached, use the error code lookup instead.

getHealthPlatformStatus() never returns available

Health Connect is a separate app, not part of the OS on every device. The status tells you which situation you are in:

CauseWhat to do
The Health Connect app is missing or outdatedCall HealthConnector.launchHealthAppPageInAppStore() and let the user install or update it
The device runs below API 26Health Connect is unavailable; hide health features
A device policy or parental control blocks health dataNothing to fix in code — explain the restriction to the user
dart
final status = await HealthConnector.getHealthPlatformStatus();
if (status != HealthPlatformStatus.available) {
  await HealthConnector.launchHealthAppPageInAppStore();
  return;
}

Permission prompt never appears

Most likely: the type is not declared in your manifest. Health Connect refuses to prompt for a permission the app never declared, and the SDK reports this as ConfigurationException with permissionNotDeclared. Every type needs its own <uses-permission> entry:

xml
<uses-permission android:name="android.permission.health.READ_STEPS" />
<uses-permission android:name="android.permission.health.WRITE_STEPS" />

Second most likely: MainActivity still extends FlutterActivity. Permission requests use registerForActivityResult, which needs a FragmentActivity host. Switch to FlutterFragmentActivity — see step two of the Android setup.

Also check: the user may have already answered. Health Connect limits how often an app can re-prompt for the same permissions; send them to Health Connect's settings instead of prompting again.

Permission status is unknown on iOS

This is correct behavior, not a bug. HealthKit deliberately refuses to disclose read-authorization status so an app cannot infer what the user is hiding. Every iOS read permission reports unknown.

Design around it: run the query and treat an empty result as valid. Do not gate your UI on read status. If you genuinely need a signal, the probe workaround explains the tradeoff.

UnsupportedOperationException on a call that works on the other platform

The API you called exists on one platform only. The common cases:

CallAvailable onWhy
updateRecord(), updateRecords()Android onlyHealthKit records are immutable
getGrantedPermissions()Android onlyHealthKit will not let apps enumerate grants
revokeAllPermissions()Android onlyiOS users revoke in Settings
A data type marked @supportedOnAppleHealth…iOS, sometimes iOS 16/17/18+No Health Connect equivalent

Check the annotation reference, and branch on HealthConnector.healthPlatform when a feature is genuinely platform-specific. The iOS update workaround covers the most common of these.

Writes succeed but the data does not appear

  • You are looking at the wrong app. Health Connect and Apple Health both scope views by source. Filter by your app.
  • The time range excludes the record. Both stores index by the record's own timestamps, not by when you wrote it. A record backdated outside your query range will not appear in it.
  • Android history limits. Health Connect only exposes the last 30 days by default. Reading older data requires HealthPlatformFeature.readHealthDataHistory. iOS has no such limit.

Reads return fewer records than expected

  • Pagination. readRecords() returns one page. Follow response.nextPageRequest until it is null — see paginating.
  • The 30-day Android window again, if you are reading history.
  • Another app owns the data and the user did not grant that type. Permissions are per data type, not per app.

Build fails after upgrading to v3.9.0+

Health Connector SDK v3.9.0 builds against Health Connect 1.2.0-alpha03, which requires SDK Extension 19 at compile time:

groovy
android {
    compileSdkExtension 19
}

If the build now passes but a write throws at runtime with UnsupportedOperationException, you have hit the separate SDK Extension 21 device check on ExerciseSessionSegmentEvent.weight. That one cannot be fixed in configuration — guard the write or omit the field. Details.

Still stuck

The Toolbox demo app runs every SDK operation against a real device. If a flow works there and not in your app, the difference is in configuration. If it fails there too, open an issue with your device, OS version, Flutter version, and the logs from a PrintLogProcessor.

Released under the Apache 2.0 License.