OUT_OF_ENERGY: the TRON error that spends the fee and sends nothing
A USDT transfer goes out, the wallet shows a fee taken, and the recipient has nothing. The transaction is in a block — it was not rejected and no node was down — and where a completed transfer reads SUCCESS this one reads OUT_OF_ENERGY. On TRON that error means what it says: the call ran out of energy partway through and stopped. Here is the mechanism, the three ways a payout run walks into it, and the fixes, from the quickest to the one that actually costs least.
What the result actually says
Sending USDT is a call into a smart contract, and contract execution on TRON is metered in energy rather than charged as a flat fee (what energy is). The sender's own energy is spent first. When it does not cover the call, the network does not stop there — it buys the rest by burning the sender's TRX at the protocol rate of 100 sun for each unit, but only as far as the transaction's own fee_limit permits. That field is not a fee anybody charges. It is a ceiling on how much of the sender's TRX this one call is allowed to burn.
Reach the ceiling with the call unfinished and execution halts. Every state change it had made is rolled back, so no tokens move, and the network writes its verdict on the transaction in the place a completed call carries SUCCESS. That verdict is the word an explorer shows beside a failed transaction, and the field a node returns as contractRet. Nothing about the transaction failed to reach the network. It reached the network and was carried out until the money for it ran out.
The TRX is spent either way
The rollback undoes the transfer. It does not undo the burn: energy consumed is energy paid for, and the sender is left short by whatever the attempt burned on its way to the ceiling, no tokens moved, and a transaction hash that a reconciliation script will happily file as a payment.
Which makes the reflex retry the expensive move. The same transfer with the same limit spends the same TRX for the same result, and a payout loop that retries its failures automatically can do it several times before a human reads the result string. Most of the failures a payout desk meets cost money quietly. This one costs money loudly and still gets missed, because the wallet reports a fee and the money is nowhere.
Why a limit that worked yesterday stops working
The recipient changed and the limit did not. This is the one a payout run meets first. A transfer to an address that already holds USDT takes about 65,000 units of energy; to an address that has never held it, the transfer must also create the recipient's token account, and that is about 131,000 — twice the appetite for the same amount of money moved. Burning for the first costs 6.5 TRX at the protocol rate, and for the second 13.1 TRX. A ceiling sized on the ordinary case is short by half the first time a new customer is paid, and nothing in the batch looks any different: it is a property of the recipient, not of the transfer.
The energy was there and is not any more. A delegation is a quantity for a term, not a subscription. What the first transfer spends is not there for the second, and when the term ends the remainder goes back to its owner. A wallet that already sent once in the same window has less than the delegation's headline figure suggests, and it is the later transfer that stops — which reads, from the outside, like the same transfer failing at random.
The limit is zero. Zero is the right value when the energy is certain, and in mode B, where we deliver the energy and broadcast the transaction ourselves, fee_limit is what we ask you to leave unset: a limit there would be nothing but a standing permission to burn the sender's TRX if something went wrong. It is also a hard stop. Zero permission means a call short by a single unit halts rather than paying for it, so a limit left at zero is a decision that holds only as long as the energy does.
Seeing it before the transaction is signed
The question behind the first trigger — how much energy does this recipient cost — is answerable before anything is signed, by two calls that reserve nothing and charge nothing.
GET /v1/address-check answers for one address: activated, holds_usdt, blacklisted, is_contract, and the expected_kind that follows from them. holds_usdt is the one that sets the size of the call.
curl -s -H "Authorization: Bearer $KEY" \ "https://api.nrg.market/v1/address-check?address=TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9" # expected_kind is "single", "double" or "custom"
POST /v1/estimate answers for a batch — up to 500 recipients in one call, each with a kind, the energy_units behind it and any warnings. single is the ordinary transfer and double the one that opens a token account. custom is the item no rule of thumb covers: the recipient turns out to be a contract with its own transfer logic, so neither standard figure applies and energy_units comes from a dry-run of the actual call. Those are the items to size a limit from one at a time, and the contract_recipient warning beside them is often the first sign that a payout address is not a wallet at all.
The fixes, easiest first
Raise the limit. One field, no infrastructure, and the stop goes away: the call finishes and the network takes what it needs. The cost does not go away with it. A limit is permission to burn, so a generous limit is a generous burn — the transfer that used to halt now completes at 13.1 TRX. Right as a floor under a payout run, wrong as the plan.
Put energy on the sender. Then there is nothing for the limit to permit. Energy comes from staking TRX, which means locking up a working balance and watching a resource budget, or from renting a delegation for the few minutes a transfer needs (what that costs right now). Either way the call is paid for in energy and no burn happens at all.
Send inside the window. Rented energy is on the wallet for a term, and an order's response carries send_before — the moment the delivery window closes, three seconds under the term you bought. Watch for that field appearing rather than for the word ready: the order is fulfilled by the delivery of energy, so completed follows it immediately. Sending after send_before puts the transfer into the network when the energy may already have gone home, which is exactly the shortfall this post is about.
Hand the signed transaction over. Mode B takes the window off your side entirely: you post an already-signed transfer, we hold it, and we broadcast it once the energy is confirmed on-chain. If a transaction we broadcast still reaches a block without executing, the position closes failed with transaction_reverted and the whole reservation is released — that cause, like every other one on the list, is never charged for. Read the name for what it is: transaction_reverted is our word for “it reached a block and did not execute”, whatever the network's own word for the refusal was, so an OUT_OF_ENERGY and a contract's own REVERT arrive under the same status. The TRX such a transaction burned on the way to that verdict is the sender's and not ours, which is the argument for the estimate at the top of this section rather than for a retry loop at the bottom of it.