Error handling

Error handling is a necessary step for all systems interacting with RippleNet. During the payment process, errors or exceptions can occur for business or technical reasons, and there are several scenarios that you need to be prepared to handle, including but not limited to the following:

Business

  • Receiver fails the payment due to AML / KYC check.
  • Sender fails the payment when the originator cancels the payment in their core system.
  • Sender does not settle treasury transfer due to rate.

Technical

  • Sender does not make call to accept the quote or to settle the payment due to a middleware issue.
  • Sender makes call either to accept the quote or to settle the payment, but due to an issue with the infrastructure or application the request is not received.
  • The nodes go out of sync and the payment expires due to an issue with the RippleNet messaging layer.

In this topic, we walk through the process for designing and building an error handling system to account for these types of issues.

Exceptions and error codes

The RippleNet Rulebook provides a standardized framework for exchanging data between members. RippleNet institutions are expected to use the ISO20022 status reason codes when returning errors to their partners. Conforming to network standards makes it easier to onboard new partners while mandating proprietary error codes results in partner compatibility issues. It is good practice for the receiver to inform the sender of the error codes they are implementing so that they can be processed.

Exception patterns

RippleNet implements a specific set of patterns for participant systems to raise and detect exceptions as part of the RippleNet payment process. The following list describes these patterns:

  • Instructed — This pattern is used when the specific participant determines that there is an error outside the direct RippleNet processing. The assumption is that the specific participant controls the payment or that the specific member can add information to the payment.
Note

RippleNet participants can't create exceptions for payments that they don't control or can't add information to.

The participant systems will call the RippleNet Fail payment operation and provide details of the failure causes (type, code and reason fields). This will result in the RippleNet Payment Object state transitioning to the value FAILED.

The other participant in the payment will obtain a business exception through the asynchronous pattern.

  • Synchronous — This pattern is used when an API call results in a direct exception determined by RippleNet. An exception raised within this pattern is provided as an HTTP error and specific error code in response to the API call.
  • Asynchronous — This pattern is used when an exception occurs to indicate that the participant does not have control of the payment in its current processing step. This pattern may be the result of the other participant explicitly failing the payment (for example, in the Instructed pattern described above), or an internal exception determined by RippleNet components.
Note

This exception is raised through a transition of the payment state to FAILED. Corresponding information about the failure is recorded in the relevant section of the RippleNet Payment Object.

Failure types and return reason types

The following list describes the failure types that participants provide, according to the standards for participant-initiated exceptions.

Type
Use
RECEIVER_DATA_VALIDATION Failures initiated by the receiver based on the validation of the payment data.
RECEIVER_LOCK_FAILURE General failure based on receiver processing prior to locking the payment and subsequent settlement.
SENDER_PROCESSING_FAILURE General failure based on receiver processing prior to locking the payment and subsequent settlement.
RECEIVER_PROCESSING_ERROR General failure based on the receiver processing the payment to the beneficiary after settlement is complete.

Note: This type is also used as the return reason type when the associated return is processed by the receiver.
BENEFICIARY_RETURN Returns performed based on a request from the beneficiary.
SENDER_RETURN Returns performed based on a request from the originator.

How to start planning for exceptions

The sending and receiving institutions must review the rulebook and the provided ISO 20022 status codes to understand the possible situations already covered; that information can be compared to the internal receiving or sending processes and mapped accordingly. Any exception that is currently part of the business workflow but is not mentioned in a pre-existing error code must be noted.

After reviewing exceptions, participants must interact and discuss which Instructed exceptions will be used on their connection. If the receiver identified an error scenario that is not listed in the Rulebook, they must formally provide that new exception to the sender so that they can add it to their handling process. Both sender and receiver must be in sync on what each error means and what actions will be taken when it occurs.

For a complete list of error codes, see the Error codes pages or the RippleNet Rulebook.

Using the Fail payment operation with RippleNet error codes

When failing a payment, a list of reasons must be provided. The reasons object is structured to match the fields listed on the RippleNet Rulebook error code list:

  • type = 8.1.1. Failure Type (mandatory)
  • code = 8.1.2 Code (mandatory)
  • reason = 8.1.2 Definition (mandatory)
Note

The reasons field requires an array. If the payment is failed for more than one reason, all appropriate error codes should be included on a single Fail payment API call.

Examples of the reasons array

The reasons field requires an array. Therefore, if you fail the payment for more than one reason, all appropriate error codes should be informed on a single Fail payment API call. As an example, if both originator and beneficiary accounts are missing from the RPO, you can use the following reason structure:

Example 1: If you fail a payment due to compliance issues (RN04) during the receiver validation process, use the following structure:

Copy
Copied!
  "reasons": [
    {
      "type": "RECEIVER_DATA_VALIDATION",
      "code": "RR04",
      "reason": "Regulatory Reason"
    }

Example 2: If both originator and beneficiary accounts are missing from the RippleNet Payment Object (RPO), use the following reasons structure:

Copy
Copied!
  "reasons": [
    {
      "type": "RECEIVER_DATA_VALIDATION",
      "code": "AC02",
      "reason": "Account number is invalid or missing"
    },
    {
      "type": "RECEIVER_DATA_VALIDATION",
      "code": "AC03",
      "reason": "Creditor account number inv or missing"
    }
  ]

Best practices for error handling

If there is a scenario for which no error code is mapped in the Rulebook, then the recommendation is to use the generic error code NARR and add an appropriate error message to pass on the desired information. However, creating a new error code for every small failure situation may cause an overflow of too many specific error codes. In this case, the use of a generic code can cover the customers needs and save time in the process.

Note

The NARR code should not be used in situations where an applicable code already exists in the Rulebook.

Working with asynchronous exceptions and polling

  • Polling efficiency: The polling interval is directly responsible for how fast exceptions are identified. Longer polling times may consume less resources but they limit how up-to-date your event data is.
  • Concurrency in polling processes: If two or more instances are querying RippleNet for failures, it is important to guarantee that no more than one instance will handle the same exception. For example, returning funds to a customer or re-sending a payment are always critical and need to happen only once per applicable exception.
  • Latency in responses: It is important to plan for the chance that a response will never arrive in time either due to network latency, connection loss, or lack of response from the counter-party. We recommend taking appropriate measures to account for the latency.

Working with payment failure points on ODL

The following table describes the various points of failure throughout the execution and settlement of a payment with the following definitions:

  • Payment initiation: Point where sender calls the Settle payment operation to execute a payment across ODL.
    • Source exchange: [Source currency] /XRP
    • XRP ledger: XRP/XRP
    • Destination exchange: XRP/ [Destination currency]
  • Outbound transfer: initiation of a payment via local rails by destination exchange
  • Beneficiary credit: final credit to the end beneficiary account
Failure point ODL action Recourse
Payment initiation Synchronous error Restart new payment
[Source currency]/XRP Funds remain in source currency Restart new payment
XRP/XRP Funds rolled back to USD Repair required and restart new payment
XRP/[Destination currency] Funds rolled back to USD Repair required and restart new payment
Outbound transfer Funds remain in destination currency at destination exchange Use Execute transfer method to initiate corrected payout
Beneficiary credit Funds remain at receiver Handled outside of RippleNet
Note

There are two transfer failure points that result in a rollback to source currency: XRP/XRP and XRP/[destination currency]. These rollbacks will occur at the current relevant rate for the return path to source currency.

Failure state examples

Warning

Payment object data may significantly differ from the examples provided in this document due to product versions, environment, digital asset exchange, and other factors. Please contact your Ripple support team with any questions.

Bitstamp USD -> XRP trade failure

Chaos Code: FAIL_SOURCE_EXCHANGE

  • Description: Failure to complete the trade of USD for XRP at Bitstamp
  • Resolution: Restart payment flow
  • Notes: Rollback-related labels may change, so do not key on them
  • Payment Object Key Fields: See Appendix 1A in the Rulebook

Bitstamp XRP withdrawal failure

Chaos Code: FAIL_INTERMEDIARY_TRANSFER_WITHDRAW

  • Description: XRP withdrawal attempt failed at Bitstamp, and XRP remains at Bitstamp. This may be indistinguishable from FAIL_INTERMEDIARY_TRANSFER_DEPOSIT .
  • Resolution: Handle carefully. Manual trades or transfers are currently required, so block further UI actions for users until resolved.
  • Notes: Rollback-related labels may change, so do not key on them
  • Payment Object Key Fields: See Appendix 1B in the Rulebook

Bitso XRP deposit failure

Chaos Code: FAIL_INTERMEDIARY_TRANSFER_DEPOSIT

  • Description: XRP deposit attempt failed at Bitso, and XRP deposit remains at Bitstamp. This may be indistinguishable from FAIL_INTERMEDIARY_TRANSFER_WITHDRAW .
  • Resolution: Handle carefully. Manual trades or transfers are currently required, so block further UI actions for users until resolved.
  • Notes: Rollback-related labels may change, so do not key on them
  • Payment Object Key Fields: See Appendix 1C in the Rulebook

Bitso XRP -> MXN trade failure

Chaos Code: FAIL_DESTINATION_EXCHANGE

  • Description: Failure to complete the trade of XRP for MXN at Bitso.
  • Resolution: Log into Bitso and manually trade, initiating a payout. Block further UI actions for users until resolved.
  • Notes: Rollback-related labels may change, so do not key on them
  • Payment Object Key Fields: See Appendix 1D in the Rulebook

Bitso MXN bank account payout failure

Chaos Code: FAIL_OUTBOUND_TRANSFER

  • Description: Failure to move MXN via local rails to Bitso.
  • Resolution: Log into Bitso and manually initiate payout.
  • Notes: Rollback-related labels may change, so do not key on them
  • Payment Object Key Fields: See Appendix 1E in the Rulebook