TER Result Codes
← Back to Transactors: Understanding the Lifecycle of a Transaction
Introduction
Every transaction in the XRP Ledger produces a result code called a TER (Transaction Engine Result). These codes communicate the outcome of transaction processing—whether it succeeded, failed, or needs to be retried. Understanding TER codes is essential for building applications that correctly handle transaction outcomes and for debugging transaction failures.
The TER code system is defined in include/xrpl/protocol/TER.h and provides a rich taxonomy of outcomes that guide both the consensus process and client applications.
TER Code Categories
TER codes are organized into distinct ranges, each indicating a different category of outcome:
-399 to -300
tel
Local
Local processing error
No
-299 to -200
tem
Malformed
Transaction is malformed
No
-199 to -100
tef
Failure
Transaction failed
No
-99 to -1
ter
Retry
Transaction may succeed later
No
0
tes
Success
Transaction succeeded
Yes
100+
tec
Claim
Transaction failed but fee claimed
Yes
tesSUCCESS (0)
The only success code. The transaction was applied successfully and achieved its intended effect.
Characteristics:
Transaction is included in a validated ledger
All intended state changes were applied
Transaction fee was charged
Sequence number was consumed
tem* Codes: Malformed Transactions
Range: -299 to -200
Malformed transactions have structural or format problems that make them permanently invalid. These transactions can never succeed, regardless of ledger state.
Common tem Codes:*
temMALFORMED
Generic malformed
Invalid transaction structure
temBAD_AMOUNT
Invalid amount
Negative, zero, or overflow
temBAD_CURRENCY
Invalid currency
Bad currency code format
temBAD_EXPIRATION
Invalid expiration
Zero or negative expiration
temINVALID_FLAG
Invalid flag
Unknown or conflicting flags
temREDUNDANT
Redundant operation
Self-send, self-trust, etc.
temDISABLED
Feature disabled
Amendment not enabled
Example Usage in Code:
Client Handling: Never retry tem* transactions—they are permanently invalid.
tef* Codes: Failure
Range: -199 to -100
Failure codes indicate that the transaction cannot succeed due to the current ledger state, but the failure is not permanent.
Common tef Codes:*
tefPAST_SEQ
Sequence already used
Transaction already applied or sequence too low
tefMAX_LEDGER
LastLedgerSequence passed
Transaction expired
tefBAD_SIGNATURE
Invalid signature
Wrong key or corrupted signature
tefBAD_AUTH
Authorization failed
Signer not authorized
tefINTERNAL
Internal error
Unexpected state (bug)
tefINVARIANT_FAILED
Invariant check failed
Transaction would violate ledger invariants
Example:
Client Handling: Generally don't retry—the transaction has a fundamental problem.
ter* Codes: Retry
Range: -99 to -1
Retry codes indicate that the transaction could not be applied now but might succeed later if ledger state changes.
Common ter Codes:*
terPRE_SEQ
Sequence too high
Wait for earlier transaction
terQUEUED
In queue
Wait for queue processing
terINSUF_FEE_B
Fee too low
Increase fee and resubmit
terNO_ACCOUNT
Account doesn't exist
Fund the account first
Client Handling: May retry after conditions change (e.g., earlier transaction applies, fee drops).
tec* Codes: Claimed Cost
Range: 100+
These codes indicate that the transaction was included in a ledger and the fee was charged, but the intended operation did not succeed. The transaction "claims" its cost (fee + sequence) but doesn't achieve its goal.
Common tec Codes:*
tecNO_DST
No destination
Destination account doesn't exist
tecUNFUNDED_PAYMENT
Insufficient funds
Not enough balance for payment
tecINSUFFICIENT_RESERVE
Reserve not met
Can't afford new object
tecFROZEN
Asset frozen
Trust line or global freeze
tecNO_PERMISSION
Not permitted
Account flags prevent operation
tecDST_TAG_NEEDED
Tag required
Destination requires tag
tecEXPIRED
Expired
Object or transaction expired
tecDIR_FULL
Directory full
Too many objects
Example Usage:
Client Handling: Transaction is final—fee was charged, but operation failed. Fix the issue and submit a new transaction.
tel* Codes: Local Errors
Range: -399 to -300
Local errors occur during local processing and are not related to consensus. The transaction is not forwarded to the network.
Client Handling: Address the local issue (fee, network, etc.) and resubmit.
The NotTEC Type
The codebase uses a special type NotTEC for functions that cannot return tec codes:
Why NotTEC exists:
Preflight runs before signature verification. If preflight could return tec codes (which claim fees), an attacker could:
Submit a malformed transaction with a valid account but invalid signature
Have the fee claimed from that account
Drain accounts without proper authorization
By returning NotTEC, preflight ensures no fees can be claimed for unsigned transactions.
Helper Functions
The TER header provides utility functions for checking result categories:
Decision Tree for Choosing Result Codes
Best Practices
Choose the right code: Match the error category to the situation
Use specific codes: Prefer
tecNO_DSTover generictecFAILED_PROCESSINGLog with context: Include helpful debug information in logs
Return early: Check cheapest conditions first, return on failure
NotTEC in preflight: Never return
teccodes from preflight
Codebase References
include/xrpl/protocol/TER.h
TER code definitions and helper functions
src/libxrpl/protocol/TER.cpp
TER string conversion implementation
Last updated

