Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.synheart.ai/llms.txt

Use this file to discover all available pages before exploring further.

The wear SDK exposes a small typed error hierarchy. Most adapters emit one of three error subtypes; vendor-specific failures bubble through originalException.

Base type

class SynheartWearError implements Exception {
  final String message;
  final String? code;
  final Exception? originalException;
}
Subtypes:
ClassCodeTrigger
PermissionDeniedErrorPERMISSION_DENIEDOS or adapter permission denied.
DeviceUnavailableErrorDEVICE_UNAVAILABLENo wearable / source available.
NetworkErrorNETWORK_ERRORCloud adapter HTTP/RPC failure.
originalException carries the platform-specific underlying error so callers can inspect when the typed code is too coarse.

Permission denied

Triggered by:
  • HealthKit refusing access to a requested HKObjectType.
  • Health Connect missing a permission grant for HeartRateRecord (etc.).
  • BLE permission revoked at OS level.
  • Vendor OAuth flow cancelled by user or rejected by vendor.
  • requestPermissions returning denied for any requested type.
Recovery:
  • For OS permissions: surface a UI rationale and call requestPermissions again with the missing types.
  • For OAuth: route the user back through the vendor’s auth URL.
  • For revoked permissions: the SDK reports ConsentStatus.revoked, distinct from denied (never granted vs previously granted).

Device unavailable

Triggered when the adapter cannot find a viable data source:
  • HealthKit not present (iPad without paired iPhone).
  • Health Connect not installed or unsupported on the Android version.
  • BLE HRM scan times out without finding a 0x180D device.
  • Vendor webhook subscription not active.
  • streamHR invoked while no underlying source is connected.
Recovery: the SDK retries on streamHR/streamHRV reconnects, but readMetrics() calls fail fast. Hosts should display a “no device connected” UI and let the user reconnect.

Network error

Triggered by HTTP/RPC failures in the cloud adapters (WHOOP, Garmin, Fitbit). The originalException wraps the underlying transport error. Common causes:
  • Vendor token expired (caller should refresh OAuth).
  • Vendor rate-limit (HTTP 429); adapters back off.
  • Server-side outage (5xx).
  • TLS validation failure.
Recovery: per-adapter, with exponential backoff. Token-related failures may surface as PermissionDeniedError instead, depending on the vendor.

Adapter-specific errors

HealthKit

CodeCause
HKErrorAuthorizationDeniedUser denied at HealthKit prompt.
HKErrorAuthorizationNotDeterminedNot asked yet.
HKErrorNoDataSample query returned empty.
HKErrorRequiredAuthorizationDeniedRequired type missing in HKHealthStore request.
The SDK maps these to PermissionDeniedError or DeviceUnavailableError as appropriate.

Health Connect

CodeCause
INSTALL_REQUIREDHealth Connect not installed on the device.
MIGRATION_REQUIREDUser must migrate from older Google Fit.
NO_PERMISSIONSPermission grant missing.
The SDK surfaces these as DeviceUnavailableError (install/migration) or PermissionDeniedError (permissions).

BLE HRM

FailureSurface
Bluetooth permission deniedPermissionDeniedError("Bluetooth").
Adapter offDeviceUnavailableError("Bluetooth disabled").
Scan timeout (no 0x180D)DeviceUnavailableError("No HRM found").
Connection lost mid-streamstreamHR emits a NetworkError-shaped event, then attempts reconnect.
Device sends malformed packetSample dropped, stream continues.

WHOOP (cloud)

FailureSurface
OAuth token expiredPermissionDeniedError; caller refreshes via WhoopProvider.
Webhook subscription invalidDeviceUnavailableError; caller re-subscribes.
RAMEN delivery channel closedCaller-transparent reconnect; final close emits no error.
fetchRawDataForFlux returns 4xxNetworkError with the vendor’s response in originalException.

Garmin (cloud)

FailureSurface
OAuth token expiredPermissionDeniedError.
Webhook arrived but REST pull (DeliveryHint.ping) failsNetworkError; no WearMetrics emitted for this event.
Rate-limited (429)Adapter backs off; caller sees no error unless persistent.

Garmin Health SDK (RTS)

FailureSurface
License missingDeviceUnavailableError("Garmin Health SDK not licensed") at initialize.
Pairing failedDeviceUnavailableError.
RTS connection dropAuto-reconnect; logged.

Apple Health XML backfill

FailureSurface
export.zip malformedSynheartWearError("Invalid Apple Health export").
XML parse errorSame; the underlying XmlParserException is in originalException.
Runtime backfill ingest failsBubbles up the runtime’s negative return code.

Logging policy

The SDK logs at info/warn and never logs:
  • Vendor OAuth tokens.
  • Personal device_ids in plain (debug builds may; production ones do not).
  • Raw HRV/RR sample bytes.
  • XML payloads beyond malformed-record line numbers.
WearMetrics snapshots are not logged. Hosts that need observability should collect them at the consumer layer.

Validation invariants

Regardless of error state:
  • WearMetrics.timestamp is always UTC ISO-8601.
  • Numeric metric values are finite (NaN/inf get filtered to null).
  • Event ordering is preserved within a single adapter; cross-adapter ordering uses timestamp.