What happened
We delegated enough Energy for a transfer, yet some clients received FAILED — OUT OF ENERGY. The incident lasted 31 hours and affected fewer than 5% of clients. This is the GasFree4you postmortem: the rental lifecycle change, our investigation and why we restored automatic reclamation after transfers.
We own the delegation lifecycle. Giving clients a way to end a rental themselves should not have left their next order short of resources.
How our Energy rental worked
We delegate Energy for one hour. Previously, our service reclaimed it immediately after a transfer; unused Energy was reclaimed after an hour.
We then let the client initiate early reclamation when a transfer was complete or the resource was no longer needed. The one-hour automatic timeout remained. Here, a client reclaiming Energy means requesting it from our service: the stake owner performs the on-chain undelegation.
It seemed to work. But a client could leave an old rental open and order a new one for the same address. The overlap between those lifecycles was the critical detail.
The Energy was there. Where did it go?
The first reports seemed contradictory: the delegation was large enough and the transfer contract consumed the same amount as before. We built an analyzer to reconstruct available Energy for each address over time.
The shortage was real. A new delegation made enough resources available, then the old order’s one-hour timeout triggered reclamation. Available Energy fell before the next transfer. “We just supplied enough” described our order record, not the address state at execution time.
The sequence behind the failure
The order of operations on one address mattered. The timeout belonged to an old rental, but its effect changed the shared resources needed by the next transfer.
- 01 · Old order A is delegated
- 02 · Transfer completes; client does not request reclamation of A
- 03 · New order B is delegated to the same address
- 04 · A reaches one hour and automatic reclamation runs
- 05 · Available Energy falls before the next transfer
What undelegation does in java-tron
We suspected a blockchain bug and opened the TRON Java source. UnDelegateResourceActuator.java contained a proportional transferUsage calculation. It explained a mechanism our order logic had overlooked.
Undelegation removes stake backing Energy. The limit falls by the corresponding resource capacity, while accumulated usage falls only by a calculated share, capped at the capacity of the withdrawn stake. Those are different quantities.
The denominator, getAllFrozenBalanceForEnergy(), includes all stake backing the address’s Energy: its own stake and received delegations, including those from other owners. This formula does not label usage as belonging to an old order while a new order remains unused.
Java · UnDelegateResourceActuator
transferUsage = (long) (receiverCapsule.getEnergyUsage()
* ((double) (unDelegateBalance) / receiverCapsule.getAllFrozenBalanceForEnergy()));
transferUsage = min(unDelegateMaxUsage, transferUsage);TRON source code: java-tron · UnDelegateResourceActuator.java (ENERGY), java-tron · AccountCapsule.getAllFrozenBalanceForEnergy().
Example: a new order, less available Energy
Take two equal delegations of 100 illustrative Energy units each. The old order has consumed 100; the new one adds another 100. Before reclamation, the limit is 200, recorded usage is 100 and available Energy is 100.
Withdrawing half the backing stake removes 100 from the limit, but only 50 from usage: 100 × 1/2. The new limit is 100, usage is 50 and only 50 remains available. A subsequent call requiring 80 no longer has enough delegated resources.
The next call needs 80 illustrative units
How we resolved the incident
We restored reclamation by our service immediately after a transfer. We no longer wait for a client request or for the rental hour to expire. Unused Energy retains its one-hour term.
This removes the dependency on client action to close a used rental. The integration lesson is to manage orders around address state and the sequence of on-chain operations.
What to check after FAILED — OUT OF ENERGY
If a USDT TRC-20 transfer or another contract call fails with OUT OF ENERGY, a rental purchase alone does not explain what happened. Resources at execution time matter.
- Find the TxID and execution result on TRONSCAN. Record the sender address and block order.
- Compare delegations and undelegations, especially older rentals expiring before the transfer. Current resources do not replace historical data.
- Check available Energy, the call estimate, fee_limit and whether TRX can cover a resource shortfall. The same error message does not prove the same cause.
- Give support the TxID, address and order time. An investigation does not require your private key or seed phrase.
TRON source code: TRON · FeeLimit and Energy cost, TRON · Transaction receipt.
What this taught us about TRON integrations
This incident tested our model of TRON resources. A separate order in a service database does not create an isolated Energy reserve on the blockchain.
Our payments and transfers expertise grows through investigations like this: from a client report and an event reconstruction to source-code review and a change in service behavior. We will keep sharing practical TRON engineering lessons in the blog.
OUT OF ENERGY questions
Why was Energy insufficient after a new rental?
In our incident, an older delegation was reclaimed after the new one arrived. That reduced the address’s shared available resources before the next transfer.
Was the entire TRON network down?
No. This was a service incident affecting fewer than 5% of our clients. Reading the protocol code explained the behavior; it does not establish a blockchain bug or network outage.
What changed after the investigation?
Our service now reclaims Energy after the transfer again, without waiting for a client request or the end of the rental hour.