Skip to content

[Liveness] Add a typed exception for an interrupted session instead of a generic FaceLivenessDetectionException #332

Description

@mattcreaser

Before opening, please confirm

  • I have searched for duplicate or closed issues.

Which UI component is this feature-request for?

Liveness

Please describe your feature-request in detail.

When a liveness check is interrupted — the user takes a call, or backgrounds the app long enough for the websocket to close — the failure delivered to onError is a bare FaceLivenessDetectionException with the message "An unknown error occurred during the Liveness flow" and a java.net.SocketException as the root cause.

There is no typed way to recognise it. FaceLivenessDetectionException has named subclasses for every case the SDK classifies (UserCancelledException, SessionNotFoundException, FaceInOvalMatchExceededTimeLimitException, SessionTimedOutException, CameraPermissionDeniedException, VideoEncodingException, and others), but an interruption falls through the coordinator's error handler to the generic constructor:

// LivenessCoordinator.kt:266-270
else -> FaceLivenessDetectionException(
    error.message ?: "Unknown error.",
    error.recoverySuggestion,
    error
) to false

so the same type and message are produced for any unclassified predictions-layer failure. The only way an integrator can identify an interruption today is to walk throwable.cause and match on java.net.SocketException — a JDK type that is no part of this SDK's contract and could change with any networking-layer update.

Observed behaviour on a device, for context on when this fires: a short background is recoverable. CameraX rebinds, frames resume, and the check continues. The session dies only once the OS closes the socket, so the grace window is set by socket lifetime rather than by anything the SDK specifies. When it does die, the host app has no reliable way to tell the user why.

The request: a typed exception — for example FaceLivenessDetectionException.SessionInterruptedException — for the case where the session ends because the connection was lost, as distinct from a check failure or a deliberate user action. That would let an integrator show "your check was interrupted, please try again" rather than a generic error, and distinguish it from a cancellation or a face-match timeout.

Code Snippet

FaceLivenessDetector(
    sessionId = sessionId,
    region = "us-east-1",
    onComplete = { /* ... */ },
    onError = { error ->
        when (error) {
            is FaceLivenessDetectionException.UserCancelledException ->
                dismiss()

            // Not expressible today: identifying this requires unwrapping
            // error.cause and matching java.net.SocketException.
            is FaceLivenessDetectionException.SessionInterruptedException ->
                promptRetry("Your check was interrupted. Please try again.")

            else ->
                showGenericError(error)
        }
    }
)

Additional information and screenshots

The exception name is a suggestion only; the team may prefer different vocabulary.

The equivalent gap exists on iOS, where an interruption is reported as .userCancelled and is therefore indistinguishable from the user pressing the close button. A typed error on both platforms would let a cross-platform integration handle interruption consistently.

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature-requestNew feature or requestlivenessThis issue relates to the Liveness component

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions