> For the complete documentation index, see [llms.txt](https://docs.caf.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.caf.io/caf-sdk/android/standalone-modules/caffacelivenesslite/handling-failures.md).

# Handling Failures

links: [Face Liveness Lite](https://app.gitbook.com/o/WK99k3S40M3U65yN1uet/s/vnCLbngSdfkIVoF3ziNX/~/edit/~/changes/96/android/standalone-modules/caffacelivenesslite)&#x20;

When a liveness check fails, the SDK returns a `LivenessLiteEvent.Failure` event. This event contains a `type` parameter, a `CafFailureType` enum that tells you exactly why the process was unsuccessful.

Understanding and handling the `type` parameter is critical for providing clear, actionable feedback to your users so they can correct the issue and try again.

#### The Failure Model

The SDK delivers failures through the `LivenessLiteEvent` sealed interface. Both capture-level and recognition-level failures are reported as `LivenessLiteEvent.Failure`, ensuring you can always access the `type` and `description`.

{% code title="LivenessLiteEvent.kt" %}

```kotlin
public sealed interface LivenessLiteEvent {

    /**
     * Liveness failure event with specific failure type.
     *
     * @param response The signed response from the server
     * @param type The specific type of failure that occurred
     * @param description User-friendly description of the failure
     */
    public data class Failure(
        val response: String,
        val type: CafFailureType,
        val description: String
    ) : LivenessLiteEvent
}
```

{% endcode %}

{% hint style="warning" %}
Ensure the JWT response is evaluated on the backend. This process must include validating the token's signature and verifying the `isAlive` and `isMatch` fields. Do not perform these validations on the client side.
{% endhint %}

#### Using the `type` Parameter

The `type` parameter returns a `CafFailureType` enum constant (e.g., `TOO_DARK` or `FACE_TOO_FAR`).

Best Practice: Do not display the raw enum name or the `description` directly to your end-users. Instead, intercept the `type` and map it to a user-friendly, localized message in your app's UI to guide them on how to fix the problem.

**Available Failure Types**

If the image capture is successful but the engine fails to authenticate or process the face, the SDK returns a `LivenessLiteEvent.Failure`.

Below is the list of possible `CafFailureType` values returned during this phase:

|          Type         | Description                |
| :-------------------: | -------------------------- |
|       `UNKNOWN`       | Generic failure            |
|  `TOO_MUCH_MOVEMENT`  | Excessive head motion      |
|      `TOO_BRIGHT`     | Over-illumination          |
|       `TOO_DARK`      | Low light conditions       |
|   `MISALIGNED_FACE`   | Face alignment failure     |
|     `FACE_TOO_FAR`    | Face too distant           |
|    `FACE_TOO_CLOSE`   | Face too close             |
|      `SUNGLASSES`     | Eye-obscuring eyewear      |
|    `OBSCURED_FACE`    | Partial face obstruction   |
|     `EYES_CLOSED`     | Closed eyes during capture |
|    `MULTIPLE_FACES`   | Multiple faces detected    |
|   `BACKGROUND_ISSUE`  | Unsuitable background      |
|     `DEVICE_ISSUE`    | Incompatible device        |
|       `EYEWEAR`       | Eyewear detected           |
|    `FACE_NOT_FOUND`   | Face detection failure     |
|    `FRAMES_BLURRY`    | Blurry frames detected     |
|     `MOTION_ISSUE`    | Device motion error        |
|   `LIGHTING_ISSUES`   | Poor lighting conditions   |
|       `REJECTED`      | Transaction rejected       |
|     `SYSTEM_ERROR`    | Internal system error      |
|       `TIMEOUT`       | Session timeout            |
|    `USER_NOT_FOUND`   | User lookup failure        |
|    `DEVICE_RESTART`   | Device state error         |
|   `PROCESSING_FAULT`  | Processing error           |
| `FACE_AUTHENTICATION` | Face authentication failed |

#### Example Implementation

Here is an example of how you might handle a `LivenessLiteEvent.Failure` and map the `type` parameter to helpful user guidance:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
fun handleLivenessFailure(failure: LivenessLiteEvent.Failure) {
    // 1. The signed server payload is available if needed
    println("Server response: ${failure.response}")

    // 2. Map the 'type' to a user-friendly message
    val userMessage = when (failure.type) {
        CafFailureType.TOO_DARK -> "It's a bit too dark. Please move to a brighter room."
        CafFailureType.FACE_TOO_FAR -> "Please bring the phone closer to your face."
        CafFailureType.EYES_CLOSED -> "Please keep your eyes open and look directly at the camera."
        CafFailureType.MULTIPLE_FACES -> "Ensure you are the only one in the frame."
        CafFailureType.TIMEOUT -> "Time ran out. Please try again when you are ready."
        CafFailureType.REJECTED,
        CafFailureType.FACE_AUTHENTICATION -> "We couldn't verify your face. Please try again."
        //...
        else -> "An unexpected error occurred (${failure.type}). Please try again."
    }

    // 3. Display the message in your UI
    showErrorDialog(userMessage)
}
```

{% endtab %}

{% tab title="Java" %}
{% code title="" %}

```java
public void handleLivenessFailure(LivenessLiteEvent.Failure failure) {
    // 1. The signed server payload is available if needed
    System.out.println("Server response: " + failure.getResponse());

    // 2. Map the 'type' to a user-friendly message
    String userMessage;

    switch (failure.getType()) {
        case TOO_DARK:
            userMessage = "It's a bit too dark. Please move to a brighter room.";
            break;
        case FACE_TOO_FAR:
            userMessage = "Please bring the phone closer to your face.";
            break;
        case EYES_CLOSED:
            userMessage = "Please keep your eyes open and look directly at the camera.";
            break;
        case MULTIPLE_FACES:
            userMessage = "Ensure you are the only one in the frame.";
            break;
        case TIMEOUT:
            userMessage = "Time ran out. Please try again when you are ready.";
            break;
        case REJECTED:
        case FACE_AUTHENTICATION:
            userMessage = "We couldn't verify your face. Please try again.";
            break;
        //...
        default:
            userMessage = "An unexpected error occurred (" + failure.getType() + "). Please try again.";
            break;
    }

    // 3. Display the message in your UI
    showErrorDialog(userMessage);
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Links:

{% content-ref url="/pages/SWa4fYvXU4QHS0rTEBa7" %}
[Face Liveness Lite](/caf-sdk/android/standalone-modules/caffacelivenesslite.md)
{% endcontent-ref %}

{% content-ref url="/pages/kzUUoJkdkppda386DUZv" %}
[Handling Failures](/caf-sdk/android/getting-started-with-the-sdk/handling-failures.md)
{% endcontent-ref %}

{% content-ref url="/pages/CjjPANiCm0TOnbldUgeg" %}
[Ui Customization](/caf-sdk/android/standalone-modules/caffacelivenesslite/ui-customization.md)
{% endcontent-ref %}

{% content-ref url="/pages/vsdoZhkDbnAXRhPVlR18" %}
[Changelog](/caf-sdk/android/standalone-modules/caffacelivenesslite/changelog.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.caf.io/caf-sdk/android/standalone-modules/caffacelivenesslite/handling-failures.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
