> 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/ios/getting-started-with-the-sdk-1/handling-failures.md).

# Handling Failures

{% hint style="warning" %}

## This guide covers version 7.0.0 and above. For versions below 7.0.0, please see the [legacy documentation](/caf-sdk/ios/getting-started-with-the-sdk-5.md).

{% endhint %}

When a liveness check fails, the SDK returns a `LivenessFailure` object. This object contains a `cause` parameter, which is a string identifier that tells you exactly why the process was unsuccessful.

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

***

### Delegate callbacks (`CerttaLivenessDelegate`)

| Delegate      | Meaning                                                                                     |
| ------------- | ------------------------------------------------------------------------------------------- |
| `didFail(_:)` | Business failure: the flow completed, but the outcome was not accepted (`LivenessFailure`). |

***

### Using the `cause` Parameter

The `cause` parameter returns a raw constant string (e.g., `"TOO_DARK"` or `"FACE_TOO_FAR"`).

Best Practice: Do not display these raw strings directly to your end-users. Instead, intercept the `cause` string 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 Causes

When using the [Iproov](https://github.com/iProov/ios) provider, if the image capture is successful but the engine fails to authenticate or process the face, the SDK returns a `FaceRecognitionFailure`.

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

#### Stable `cause` values

| `cause`                                                     | Hint                    |
| ----------------------------------------------------------- | ----------------------- |
| `unknown`                                                   | Unclassified            |
| `too_much_movement`                                         | Excessive head movement |
| `too_bright`, `too_dark`, `lighting_issues`                 | Lighting                |
| `misaligned_face`                                           | Not aligned with guide  |
| `eyes_closed`                                               | Eyes closed             |
| `face_too_far`, `face_too_close`                            | Distance                |
| `sunglasses`, `eyewear`                                     | Glasses                 |
| `obscured_face`                                             | Face covered            |
| `multiple_faces`                                            | More than one face      |
| `face_not_found`                                            | No face in region       |
| `frames_blurry`                                             | Too blurry              |
| `motion_issue`                                              | Motion                  |
| `background_issue`                                          | Background / contrast   |
| `device_issue`, `device_restart`                            | Device                  |
| `system_error`                                              | System                  |
| `rejected`, `timeout`, `user_not_found`, `processing_fault` | Transaction / server    |

***

### Example Implementation

Here is an example of how you might handle a `LivenessFailure` and map the `cause` parameter to helpful user guidance:

```swift
func mapFailureToUX(_ failure: LivenessFailure) -> (code: String, message: String) {
    switch failure {
    case .imageCaptureFailure(let text):
        return ("image_capture", text)
    case .faceRecognitionFailure(_, let cause):
        let code = cause.lowercased()
        let message = localizedHint(forCause: code) ?? "Verification failed. Please try again."
        return (code, message)
    }
}

private func localizedHint(forCause cause: String) -> String? {
    switch cause {
    case "too_dark", "too_bright", "lighting_issues":
        return "Improve lighting and try again."
    case "multiple_faces":
        return "Only one person should be in the camera."
    case "timeout":
        return "Time ran out. Please try again."
    default:
        return nil
    }
}
```


---

# 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/ios/getting-started-with-the-sdk-1/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.
