{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-products/payments-odl/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"Exception handling","description":"User guides, API reference, and support resources.","siteUrl":"https://docs.ripple.com/products/custody","lang":"en-US","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"exception-handling","__idx":0},"children":["Exception handling"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This page explains how payment senders can validate payments against their receiving partner's RPO schema, and generate \"instructed\" business exceptions."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"<!-- -->"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Test Harness generates instructed exceptions in \"Sending Test\" mode only (as mock receiver)."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"instructed-exceptions","__idx":1},"children":["Instructed exceptions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["There are three types of RippleNet exceptions:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Instructed"]},": exceptions created by the member who controls the payment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Asynchronous"]},": exceptions created by ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["other"]}," members who control the payment, as well as RippleNet internal exceptions."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Synchronous"]},": RippleNet HTTP error in response to an API request."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"rpo-validation","__idx":2},"children":["RPO validation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Schema violations trigger a payment failure. Each schema violation is mapped to an error code defined in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["errorMapFilename"]}," property; and each error code is added to the payments failure reasons."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Caution"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Accepted payments are only processed by the mock receiver Test Harness if the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["user_info"]}," is in the form of a JSON object. If the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["user_info"]}," is an array (as allowed by the RippleNet API), the payment is ignored."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"triggering-exceptions","__idx":3},"children":["Triggering exceptions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Exceptions are generated in two ways:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the inbound RPO doesn't align with the active RPO schema, the payment fails with a \"RECEIVER_DATA_VALIDATION\" failure type and an error code determined by the error mapping file."]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the inbound RPO contains the \"instructed_failure\" key, the payment fails with both the failure type and an error code determined by the error mapping file."]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To trigger an instructed business exception, add a field called ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["instructed_failure"]}," to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["user_info"]}," during the Accept quote step. Set the value of this field to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["failure_type"]},"-",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["failure_code"]}," (that is, type + hyphen + code), for example:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"\t{\n\t\t\"instructed_failure\": \"RECEIVER_DATA_VALIDATION-AC01\"\n\t}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"failure-types-and-codes","__idx":4},"children":["Failure types and codes"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Test Harness supports all ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["receiver"]}," failure types: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RECEIVER_DATA_VALIDATION"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RECEIVER_LOCK_FAILURE"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RECEIVER_PROCESSING_ERROR"]},". The failure type determines the stage at which the payment is failed."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"sender-return-requests","__idx":5},"children":["Sender return requests"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For returns processed by the receiver, the primary failure type is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RECEIVER_PROCESSING_ERROR"]},". With RippleNet Test Harness 1.6.0 and higher, you can use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SENDER_RETURN"]}," for returns performed based on a request from the payment sender."]}]},"headings":[{"value":"Exception handling","id":"exception-handling","depth":1},{"value":"Instructed exceptions","id":"instructed-exceptions","depth":2},{"value":"RPO validation","id":"rpo-validation","depth":2},{"value":"Triggering exceptions","id":"triggering-exceptions","depth":2},{"value":"Failure types and codes","id":"failure-types-and-codes","depth":2},{"value":"Sender return requests","id":"sender-return-requests","depth":3}],"frontmatter":{"seo":{"title":"Exception handling"}},"lastModified":"2025-10-29T17:55:09.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/products/payments-odl/api-docs/ripplenet/test-automation/sender-testing/exception-handling","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}