---
title: Stepping through DaVinci flows
description: Explains how to navigate DaVinci flows in an Android application by handling different node types (`ContinueNode`, `SuccessNode`, `ErrorNode`, `FailureNode`) and their collectors.
component: orchsdks
page_id: orchsdks:davinci:usage/android/03-stepping-through-davinci-flows
canonical_url: https://developer.pingidentity.com/orchsdks/davinci/usage/android/03-stepping-through-davinci-flows.html
revdate: Fri, 9 Jan 2026 17:23:51 +0000
keywords: ["DaVinci", "Android", "Flows", "Nodes", "Collectors", "Navigation"]
section_ids:
  starting_a_davinci_flow: Starting a DaVinci flow
  determining_davinci_flow_node_type: Determining DaVinci flow node type
  continue_node_type_android: Handling DaVinci flow collectors in continue nodes
  node-next: Continuing a DaVinci flow
  error_node_type_android: Handling DaVinci flow error nodes
  failure_node_type_android: Handling DaVinci flow failure nodes
  success_node_type_android: Handling DaVinci flow success nodes
---

# Stepping through DaVinci flows

[icon: circle-check, set=far]PingOne [icon: android, set=fab]Android

* [Install](01-installing-the-davinci-module.html)

* [Configure](02-configuring-the-davinci-module.html)

* **Navigate**

To authenticate your users the DaVinci module for Android must start the flow, and step through each node.

|   |                                                                                                                                 |
| - | ------------------------------------------------------------------------------------------------------------------------------- |
|   | For information on which connectors and fields the DaVinci module supports, refer to [Compatibility](../../compatibility.html). |

## Starting a DaVinci flow

To start a DaVinci flow, call the `start()` method:

Start a DaVinci flow

```kotlin
val node = daVinci.start()
```

## Determining DaVinci flow node type

Each step of the flow returns one of four node types:

* `ContinueNode`

  This type indicates there is input required from the client. The `node` object for this type contains a `collector` object, which describes the information it requires from the client.

  Learn more in [Handling DaVinci flow collectors in continue nodes](#continue_node_type_android).

* `SuccessNode`

  This type indicates the flow is complete, and authentication was successful.

  Learn more in [Handling DaVinci flow success nodes](#success_node_type_android).

* `ErrorNode`

  This type indicates an error in the data sent to the server. For example, an email address in an incorrect format, or a password that does not meet complexity requirements.

  You can correct the error and resubmit to continue the flow.

  Learn more in [Handling DaVinci flow error nodes](#error_node_type_android).

* `FailureNode`

  This type indicates that the flow could not be completed and must be restarted. This can be caused by a server error, or a timeout.

  Learn more in [Handling DaVinci flow failure nodes](#failure_node_type_android).

You can use the helper functions to determine which node type the server has returned:

Determine `node` type.

```kotlin
when (node) {
    is ContinueNode -> {}
    is ErrorNode -> {}
    is FailureNode -> {}
    is SuccessNode -> {}
}
```

## Handling DaVinci flow collectors in continue nodes

The `ContinueNode` type contains `collectors`. These collectors define what information or action to request from the user, or client device.

|   |                                                                                                                                            |
| - | ------------------------------------------------------------------------------------------------------------------------------------------ |
|   | For a list of supported collectors, refer to [Supported PingOne fields and collectors](../../compatibility.html#supported-davinci-fields). |

There are specific collector types. For example there are `TextCollector` and `PasswordCollector` types.

To complete a DaVinci flow we recommend that you implement a component for each connector type you will encounter in the flow. Then you can iterate through the flow and handle each collector as you encounter it.

Access collectors in a `ContinueNode`

```kotlin
node.collectors.forEach {
    when(it) {
        is TextCollector -> it.value = "My First Name"
        is PasswordCollector -> it.value = "My Password"
        is SubmitCollector -> it.value = "click me"
        is FlowCollector -> it.value = "Forgot Password"
    }
}
```

## Continuing a DaVinci flow

After collecting the data for a node you can proceed to the next node in the flow by calling the `next()` method on your current `node` object.

Continue a DaVinci flow using `next()`

```kotlin
val next = node.next()
```

|   |                                                                                                                                                                  |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | You do not need to pass any parameters into the `next` method as the DaVinci module internally stores the updated object, ready to return to the PingOne server. |

The server responds with a new `node` object, just like when starting a flow initially.

Loop again through conditional checks on the new node's type to render the appropriate UI or take the appropriate action.

## Handling DaVinci flow error nodes

DaVinci flows return the `ErrorNode` type when it receives data that is incorrect, but you can fix the data and resubmit. For example, an email value submitted in an invalid format or a new password that is too short.

You can retrieve the error message by using `node.message()`, and the raw JSON response with `node.input`.

Displaying the reason for an error

```kotlin
val node = daVinci.start() // Start the flow

//Determine the Node Type
when (node) {
    is ContinueNode -> {}
    is ErrorNode -> {
        node.message() // Retrieve the cause of the error
    }
    is FailureNode -> {}
    is SuccessNode -> {}
}
```

|   |                                                                                                          |
| - | -------------------------------------------------------------------------------------------------------- |
|   | This is different than a `FailureNode` type, which you cannot resubmit and must restart the entire flow. |

You can retain a reference to the `node` you submit in case the next `node` you receive is an `ErrorNode` type. If so, you can re-render the previous form, and inject the error information from the new `ErrorNode` node.

After the user revises the data call `next()` as you did before.

## Handling DaVinci flow failure nodes

DaVinci flows return the `FailureNode` type if there has been an issue that prevents the flow from continuing. For example, the flow times out or suffers a server error.

You can retrieve the cause of the failure by using `node.cause()`, which is a `Throwable` object.

Handling receipt of a `FailureNode` type

```kotlin
val node = daVinci.start() // Start the flow

//Determine the Node Type
when (node) {
    is ContinueNode -> {}
    is ErrorNode -> {}
    is FailureNode -> {
        node.cause() // Retrieve the error message
    }
    is SuccessNode -> {}
}
```

You should offer to restart the flow on receipt of a `FailureNode` type.

## Handling DaVinci flow success nodes

DaVinci flows return the `SuccessNode` type when the user completes the flow and PingOne issues them a session.

To retrieve the existing session, you can use the following code:

Handling receipt of a `SuccessNode` type

```kotlin
val user: User? = daVinci.user()

user?.let {
    it.accessToken()
    it.revoke()
    it.userinfo()
    it.logout()
}
```
