Errors and Troubleshooting
Common errors and troubleshooting tips
ACH Returns
After an ACH payment has been posted, it can be returned and clawed back from your account for a number of reasons. For example, a bank could determine that there are insufficient funds to complete the transfer, or a consumer can contact their bank and flag the transaction as unauthorized. If a debit transfer results in an ACH return, the funds will be automatically clawed back in a return sweep. If a credit transfer experiences an ACH return, the funds will be returned to your Ledger available balance.
If an ACH transfer is returned, its status will be returned
. All returned ACH transactions will have an ACH return code. By reading the code, you can troubleshoot returned transactions. For a full list of ACH return codes, see ACH Return Codes.
Return Code | Description | Notes | Troubleshooting |
---|---|---|---|
R01 | Insufficient funds | Available balance is not sufficient to cover the dollar amount of the debit entry. | If you are submitting the transfer on a Friday, we recommend using Same-Day ACH to decrease the likelihood of the user's account balance dipping below the transfer amount over the weekend. |
R03 | No account or unable to locate account | The account number structure is valid, but the account number does not correspond to an existing account, or the name on the transaction does not match the name on the account. | Prompt the user to link another account via Plaid Link and use this newly linked account to create the transfer. |
R09 | Uncollected funds | Available balance is sufficient, but the collected balance is not sufficient to cover the entry | Retry the transaction a few days later after any large "holds" on the user's account have been released. |
R10 | Customer advises not authorized | Member advises not authorized, notice not provided, improper source document, or amount of entry not accurately obtained from source document. | Make sure you add proper WEB debit authorization language to your "pay with bank" UX to protect against exposure of returns of over 60 days. Unlike other ACH return codes, you cannot resubmit a payment after encountering an R10 error. |
A returned transfer can be retried up to 2 times. When you try to reprocess a returned transfer, the description
field in your /transfer/create
request must be "Retry 1"
or "Retry 2"
to indicate that it's a retry of a previously returned transfer. Note that retries are only allowed for transfers returned as R01 or R09.
RTP Failures
Plaid performs various checks within /transfer/authorization/create
to fail upfront and as early as possible if the RTP or FedNow transfer won't succeed. However, due to the asynchronous nature of the RTP and FedNow payment networks, it is still possible for transfers to fail after authorization due to a rejection by the receiving bank or an issue in the payment network. Failures in the real-time networks are fairly rare (<1%), and often indicate that the consumer bank account itself is in an unusable state.
If the RTP transfer failed, the status will be failed
and an error code will be present in the return_code
transfer property. For the following failure codes, further attempts to use this bank account for payouts via the real-time network are unlikely to succeed. Instead, we recommend that you prompt your user to link a different bank account via Plaid Link.
Return Code | Description | Notes |
---|---|---|
AC03 | Creditor account is invalid | Account number is not recognized as valid by the receiving bank. |
AC04 | Account closed | The account is closed and no longer active. |
AC06 | Account is blocked | Receiving bank has placed a block on the account, for various operational or legal reasons. |
E997 | Timeout clock has expired | The timeout for processing this transaction was exceeded in the FedNow network. You can safely retry the payment with a different idempotency key. |
Error codes
For a list of error codes specific to transfer, and their meaning, see Transfer error codes.
Handling 500 errors in transfer creation
Due to unexpected circumstances, you may rarely encounter a 500 HTTP error when creating a transfer via /transfer/authorization/create
or /transfer/create
. In this case, it's possible that the authorization or transfer was created successfully, but the response was not received. It is highly recommended to utilize the idempotency_key
field in /transfer/authorization/create
so that retries in this scenario are safe to perform and will not result in duplicate authorizations. Retrying /transfer/create
with the same authorization_id
is guaranteed to only ever produce a single transfer.
Whether you retry the request to /transfer/create
or not, it's possible that the first request succeeded, and so your integration should be prepared to consume events from /transfer/event/sync
that you may not have seen the transfer_id
for previously. It is recommended you have a recovery process in place, either by logging these instances for manual review and reconciliation, or automatically reconciling by pulling the transfer details via /transfer/get
and using the transfer.metadata
property to utilize any client-side data you attached to the transfer for reference. Another way to determine if a transfer creation succeeded after receiving a 500 error from /transfer/create
is to follow up with a call to /transfer/get
using the authorization_id
you received from /transfer/authorization/create
. If the transfer was actually created, you will receive a successful response containing the transfer details. If it wasn't, you will receive a 404 HTTP error with the NOT_FOUND
error code.