Skip to main content

Error Handling

AFCore reports failures the same way on Android and iOS. Reads return data or throw an AFException; sign-in and submissions return an AFResult that says whether the operation succeeded. Every message the SDK produces is safe to show a member, so your app can surface errors without writing its own copy.

What you can do​

  • Show AFException.message or AFResult.statusMessage directly -- they are member-friendly and never contain hosts, stack traces or server internals.
  • Branch on AFException.kind to tell "offline" from "server error" from "session expired", identically on every platform.
  • Branch on errorCode when the backend refuses a request with a machine-readable reason.
  • Log technicalMessage for support and crash reports (never show it to the member).
  • Tell "submitted now" from "saved for automatic delivery" with AFResult.queued.

Key types​

TypeWhat it is for
AFResultOutcome of sign-in and submissions: status, statusMessage, queued, and the exception when one occurred
AFExceptionThrown by reads and failed calls: member-safe message, kind, errorCode, errors (the server's validation messages), technicalMessage
AFErrorKindNO_CONNECTION, TIMEOUT, SECURE_CONNECTION, UNAUTHORIZED, CLIENT_ERROR, SERVER_ERROR, INVALID_RESPONSE, UNKNOWN

Queued submissions. When a self-report, barcode check-in or Fit@Home selfie is made without a connection, the SDK saves it and returns status == true with queued == true. It is delivered automatically once the device is back online -- do not retry it yourself.

Reads that fail. Reads added in 1.12 always throw. Reads that existed in 1.11 return an empty result on failure unless you build the config with throwOnReadFailure(true), which is recommended so that an empty result always means "no data". See Upgrading to 1.12.

Sessions. Token refresh is automatic; your app never handles an expired token. When a session cannot be recovered, authentication().sessionState moves to SESSION_EXPIRED -- see Session Management.

Example​

lifecycleScope.launch {
try {
val favorites = AFCore.locations().getFavorites() // 1.12 reads always throw on failure
render(favorites)
} catch (e: AFException) {
when (e.kind) {
AFErrorKind.NO_CONNECTION, AFErrorKind.TIMEOUT -> showRetry(e.message)
else -> showError(e.message)
}
crashReporter.log("AFCore ${e.kind}: ${e.technicalMessage}")
}
}

For an AFResult, check status first, then queued, and show statusMessage when status is false.

Learn more​

See the API Reference for AFResult, AFException and AFErrorKind. Complete integration guides are in AIDE Docs.