RTP Transfer Error Codes
An RTP transfer initiated with transferFunds can fail in two places:
- Synchronously: the mutation returns a
UserErrorinstead of aUnifiedFundsTransfer. Nothing was created; correct the input and retry. - Asynchronously: the mutation returns a
UnifiedFundsTransferthat later moves toFAILED. For the complete list offailureReasonvalues, what each one means, and how to handle it, see Transfer Failure Reasons.
This page covers the synchronous codes, the fee-specific errors, and how the two paths relate. It assumes you have read Transfer Funds API.
Synchronous UserError codes
Each error carries a code, a human-readable description, and an errorPath pointing at the offending input field, including list indices when the field repeats. A single response can contain multiple errors. Handle the list, not just the first entry.
Synchronous UserError codes for RTP transfers
| Code | When | Typical errorPath |
|---|---|---|
INVALID_AMOUNT_SPECIFICATION | Both or neither of source.amount / destination.amount were provided. Exactly one is required. | input.source.amount or input.destination.amount |
MAX_LENGTH_REACHED | paymentRelatedInformation exceeds 140 characters. | input.source.bankTransferDetails.paymentRelatedInformation |
INVALID_INPUT | paymentRelatedInformation contains characters the RTP network does not allow. | input.source.bankTransferDetails.paymentRelatedInformation |
NETWORK_NOT_SUPPORTED | The destination bank is not an RTP network participant. | input.destination.id or input.destination.usBankAccount.routingNumber |
DESTINATION_BANK_NOT_ACTIVE | The destination bank is an RTP participant but is not currently active on the network. | same as above |
AMOUNT_LIMIT_EXCEEDED | The amount exceeds the RTP transaction limit. | input.source.amount |
SAME_ACCOUNTS | Source and destination are the same account. | input.destination.id |
ACCOUNT_NOT_FOUND | The source or destination account does not exist. | input.source.id or input.destination.id |
TRANSFER_NOT_SUPPORTED_ON_PRODUCT | The account's product configuration does not permit this transfer. | input.source.id or input.destination.id |
TRANSFER_NOT_SUPPORTED | No transfer method supports the given source and destination combination. | — |
NETWORK_NOT_SUPPORTED and DESTINATION_BANK_NOT_ACTIVE returned this way mean the transfer was rejected up front: no UnifiedFundsTransfer exists, so there is nothing to reconcile.
ACCOUNT_NOT_ACTIVE is not confirmed as a synchronous code for RTP transfers. If the destination account exists but cannot receive, expect it as a failureReason on a created transfer instead; see Transfer Failure Reasons.
{
"data": {
"transferFunds": {
"__typename": "UserError",
"errors": [
{
"code": "NETWORK_NOT_SUPPORTED",
"errorPath": ["input", "destination", "id"],
"description": "Destination routing number is not an RTP network participant"
}
]
}
}
}
Customer fee errors
Errors specific to transfers that include customerFees.
Synchronous UserError codes
| Code | When | Typical errorPath |
|---|---|---|
INVALID_CHARGE_FROM | The fee's chargeFrom names the side whose amount you specified. The fee must charge the other side. | input.customerFees.chargeFrom |
CUSTOMER_FEE_NOT_SUPPORTED | The fee's chargeFrom side is an external bank account, which cannot be charged a fee. | — |
Asynchronous failureReason values
| Reason | When |
|---|---|
FEE_COLLECTION_FAILED | The fee could not be collected, for example due to insufficient balance on the charged account. The transfer does not proceed. |
FEE_REVERSED | The transfer failed after its fee was collected. The fee was automatically returned. |
FEE_REVERSAL_FAILED | The transfer failed and the collected fee could not be automatically returned. Contact support. |
Migrating from the async-only behavior
Before this rollout, destination-eligibility and paymentRelatedInformation problems could only report asynchronously, as a failureReason on a UnifiedFundsTransfer that reached FAILED. Now they report synchronously, as a UserError at initiation, and no transfer is created. The underlying problem is the same; only the timing and the code differ.
| Problem | Before 2026-08-17 (async) | Now (sync) |
|---|---|---|
| Destination not an RTP participant | failureReason: NETWORK_NOT_SUPPORTED | NETWORK_NOT_SUPPORTED on input.destination.* |
| Destination bank not active on the network | failureReason: DESTINATION_BANK_NOT_ACTIVE | DESTINATION_BANK_NOT_ACTIVE on input.destination.* |
Bad paymentRelatedInformation | failureReason: PAYMENT_RELATED_INFORMATION_INVALID | INVALID_INPUT / MAX_LENGTH_REACHED on the field |
If your integration only handles these conditions as an async failureReason, add handling for the synchronous UserError too. A transfer that fails synchronously creates nothing, so any reconciliation logic keyed to a UnifiedFundsTransfer in FAILED will not see it.
Handling guidance
- Treat a
UserErroras an input problem: fix the request and resubmit. - Treat a
failureReasonas terminal for that transfer. Funds, and any collected fees, return or never moved. Submit a new transfer if appropriate. See Transfer Failure Reasons for which reasons allow a retry and which do not. - Always send a unique
idempotencyKeyper attempt. Reuse a key only to safely retry the identical request.
See also
- Transfer Failure Reasons: the complete
failureReasonreference, grouped by the action to take. - Transfer Funds API: request shape, idempotency, and payment-information rules.