Skip to main content

Transfer Failure Reasons

Overview

When a transfer fails, its failureReason tells you why. This page groups the reasons you can receive on a Real-Time Payments transfer by the action to take.

Group your handling by action, not by individual value. Highnote adds values to these enums, and can move an existing condition to a more precise value. A handler keyed to one value can stop matching after a change like that, while the transfer outcome stays the same.

For Instant Network Transfer failures, see Transfer failure reasons on the Instant Network Transfers page.

For the synchronous UserError codes that can preempt some of these failures on RTP transfers submitted through transferFunds, see RTP Transfer Error Codes.

Where to read the failure

Three fields report a failure, and they do not always carry the same value.

FieldEnumWhat it describes
UnifiedFundsTransfer.failureReasonUnifiedFundsTransferFailureReasonWhy the transfer failed end to end.
UnifiedFundsTransferRtpStep.failureReasonUnifiedFundsTransferFailureReasonWhy the RTP step failed.
OriginatedRtpTransfer.failureReasonRtpTransferFailureReasonWhy the RTP transfer itself failed.

Read the RTP transfer first when you need the most specific answer. Fall back to the Unified Funds Transfer value when no RTP transfer exists, which happens when validation stops the transfer before Highnote sends it.

note

Three conditions lose detail on the Unified Funds Transfer. CONFIGURATION_ERROR, INVALID_FIELD_DATA, and REQUIRED_FIELD_MISSING all report there as INTERNAL_SERVER_ERROR. Separately, and with no loss of meaning, SAME_ACCOUNTS on the RTP transfer is named SOURCE_AND_DESTINATION_ACCOUNTS_SAME on the Unified Funds Transfer.

The In which enum column in the tables below records which enum defines a value. It does not tell you which surface produced your specific failure. Read the failureReason you received rather than inferring it from that column.

An INTERNAL_SERVER_ERROR on a Unified Funds Transfer is therefore not always a Highnote fault. Read the RTP transfer before you retry, and see Duplicate submissions.

Group 1: RTP cannot deliver this transfer

The receiving bank or the rail cannot accept the transfer. Route the payment to another rail, such as ACH or Wire. For the first two values below, retrying the same transfer on RTP fails identically.

Usually caught before the transfer is created

NETWORK_NOT_SUPPORTED and DESTINATION_BANK_NOT_ACTIVE are normally rejected synchronously as a UserError, before Highnote creates a transfer. See RTP Transfer Error Codes. They can still appear below as a failureReason, most often when the destination becomes ineligible after the pre-flight check passes.

Failure reasonIn which enumMeaning
NETWORK_NOT_SUPPORTEDBothThe receiving bank does not participate in RTP.
DESTINATION_BANK_NOT_ACTIVEBothThe receiving bank participates in RTP but is not active to receive.
PROVIDER_NETWORK_DISABLEDBothThe rail is disabled at the partner bank. No transfer on this network can currently succeed. The state can be cleared, so a later attempt may succeed. Do not wait on it for a time-sensitive payment.
PROVIDER_NOT_SUPPORTEDBothThe partner bank does not support this rail.

NETWORK_NOT_SUPPORTED and DESTINATION_BANK_NOT_ACTIVE describe two different bank states. They call for the same routing decision. Match both.

Build your fallback on this whole group

The Transfer Funds API does not fall back to same-day ACH. You build that fallback. Match every value in this group, not one value. Highnote can add a value to this group, and a fallback keyed to a single value will stop firing when that happens.

Group 2: Retry later

The condition is temporary. The same request can succeed on a later attempt.

Failure reasonIn which enumMeaning
TIMEOUTBothThe network or the receiving bank did not answer in time.
NETWORK_ERRORBothThe network rejected the message for a system condition.
DAILY_LIMIT_EXCEEDEDBothA daily count or value limit was reached. Retry the next day.
A timeout is not proof that the payment did not settle

TIMEOUT means Highnote did not receive an answer. It does not confirm that the receiving bank rejected the payment. Check the transfer status before you resend, and use a new idempotency key only when you have confirmed the first attempt failed. See Idempotency.

Group 3: Change the request and resubmit

The request is the problem. Correct it and send a new transfer.

Failure reasonIn which enumWhat to change
AMOUNT_LIMIT_EXCEEDEDBothThe amount is above a per-transaction maximum. Reduce the amount.
AMOUNT_MINIMUM_NOT_METBothThe amount is below a rail or agreement minimum. Increase the amount.
INVALID_AMOUNTBothThe amount is missing, malformed, or not the agreed value.
CURRENCY_MISMATCHBothThe currency does not match the account or the rail.
INSUFFICIENT_FUNDSBothThe source account does not hold the amount. Fund the account and retry.
PAYMENT_RELATED_INFORMATION_INVALIDUnified Funds Transfer onlypaymentRelatedInformation holds a disallowed character or is too long. See Payment information rules.
SOURCE_AND_DESTINATION_ACCOUNTS_SAMEUnified Funds Transfer onlyThe source and the destination are the same account.
SAME_ACCOUNTSRTP transfer onlyThe same condition, reported on the RTP transfer.
INVALID_FIELD_DATARTP transfer onlyA field failed validation at the partner bank. Reports as INTERNAL_SERVER_ERROR on the Unified Funds Transfer.
Usually caught before the transfer is created

Most paymentRelatedInformation problems on RTP transfers submitted through transferFunds are rejected synchronously as INVALID_INPUT or MAX_LENGTH_REACHED, before Highnote creates a transfer. See RTP Transfer Error Codes. PAYMENT_RELATED_INFORMATION_INVALID above covers the same condition reported asynchronously.

Group 4: Terminal

The transfer will not succeed as sent. Do not retry the same request unchanged. One value, TRANSFER_NOT_PERMITTED, can also mean a configuration problem on your side that you can fix.

Failure reasonIn which enumMeaning
ACCOUNT_CLOSEDBothThe destination account is closed.
ACCOUNT_NOT_FOUNDBothThe destination account does not exist at the receiving bank.
ACCOUNT_NOT_ACTIVEBothThe destination account exists but cannot receive.
ACCOUNT_FROZENBothThe destination account is blocked.
RISK_DECLINEBothA risk control declined the transfer.
TRANSFER_NOT_PERMITTEDBothHighnote configuration or the receiving bank did not permit the transfer. See below.

RISK_DECLINE can come from Highnote's own risk controls or from the receiving bank. Retrying the same transfer returns the same result. Contact Highnote to review the decline, and do not present it to your customer as a decision by the receiving bank.

TRANSFER_NOT_PERMITTED has two causes that need opposite responses, and the failure reason does not tell you which one you hit.

Highnote did not permit the transfer. Your product or account configuration does not allow it. The transfer type is not enabled on the product, the funding card is not supported, an account-holder condition is not met, or a required feature is off. Validation returns this before Highnote sends anything, so no bank saw the transfer. Another rail does not help. Check your product configuration, or contact Highnote.

The receiving bank refused the transfer. Causes include customer instruction, a legal or regulatory restriction, and account eligibility at the receiving bank. This is terminal for that destination. Offer another payout method.

If a transfer that used to work starts returning TRANSFER_NOT_PERMITTED, check your own configuration first.

Duplicate submissions

The receiving bank rejects a transfer it identifies as a duplicate. Highnote reports this as CONFIGURATION_ERROR on OriginatedRtpTransfer, and as INTERNAL_SERVER_ERROR on UnifiedFundsTransfer.

Do not retry on either value. A duplicate rejection usually means the first payment already exists at the receiving bank. Query the earlier transfer and confirm its status before you send anything else. See Idempotency.

Complete enum reference

This page covers the reasons a Real-Time Payments transfer returns. For every value in each enum, including values that apply to other rails, see: