
Among cryptocurrency users, there is a widely held belief: if you enter the correct address, choose the right network, and have enough of the native token to cover the fee, the transaction will go through. In the overwhelming majority of cases, that belief holds true.
But every blockchain has its own hidden rules - rules that only surface in very specific situations. And when they do, a transaction can fail even though, from your perspective, everything was done correctly.
That is exactly what happened to us when a customer of our swapping service, Rabbit.io, swapped LTC for SOL. The amount was tiny - less than 0.0003 SOL, which at current prices is under three cents. In many of my previous articles, I have mentioned that we do not impose upper limits on swaps. Yes, we often process extremely small amounts as well.
When we attempted to send the requested SOL, we ran into a problem. The address was correct. The network was Solana Mainnet. Our balance was sufficient. The fee was accounted for. Yet the transaction kept failing, again and again.
The explanation turned out to be unexpected - even for us. And when we shared it with the client, he did not believe it at first either. The incident made me wonder: how many similar hidden pitfalls exist across different blockchains?
I decided to investigate and compile the most interesting examples - cases that could catch even me off guard, despite the fact that I process a wide range of cryptocurrency exchanges on a daily basis.
Many people have heard that on Solana, in order to receive SPL tokens - such as USDT, USDC, and others - at an address that has never held those tokens before, the address needs to have a small amount of SOL. Strictly speaking, that is not entirely accurate, but there is some truth to it.
Each token is stored in a separate Associated Token Account (ATA), and creating that account costs roughly 0.002 SOL. However, even if the recipient has zero SOL, the tokens can still be received - because it is the sender who pays for creating the ATA, not the recipient.
What is far less known is that a similar requirement can sometimes apply to transfers of native SOL itself. That is exactly what happened to us when we tried to send the tiny amount requested by our client.
On Solana, an account is not just a string of characters representing an address. It is an actual record stored in the current state of the blockchain. That record occupies disk space on validators' nodes - and storage is not free.
This mechanism is known as rent exemption. For an account to exist, its balance must exceed a certain minimum - effectively the cost of two years of storage rent.
This value is not fixed forever, but at the moment, for a basic system account (a regular wallet), the minimum is 890,880 lamports, or 0.00089088 SOL.
If an address does not yet exist on-chain (that is, its balance is zero), the first transaction that attempts to create the account with an amount below this threshold will be rejected.
That is exactly what was happening in our case. We were sending slightly less than 0.0003 SOL to a brand-new address - roughly three times below the required threshold. Our client refused to believe such a rule even existed. And to be fair, we struggled to find any clear statement of it in Solana's official documentation. The only indirect confirmation we found was in the description of the RPC method getMinimumBalanceForRentExemption, which implies this rule - though it does not explicitly spell it out.
There is an important nuance here. We had previously sent such tiny amounts to customers many times without any issues. From practical experience, we knew that Solana allows transfers of arbitrarily small sums.
And that is true - but only if the recipient account already exists. If it is the second, third, or hundredth incoming transaction, the address can receive even 1 lamport. But when an account is being created for the first time, the rent exemption check applies.
The issue we encountered on Solana is actually a specific case of a broader pattern. In several networks, an address as a cryptographic object and an account as an entry in the distributed ledger are two different things. Without a minimum initial balance, the account simply does not exist.
On the XRP Ledger, every new account must receive a minimum reserve of 1 XRP. In the early days of the network, this requirement was much higher - 200 XRP at launch, later reduced to 50 XRP, then 20 XRP, then 10 XRP. As the price of XRP increased over time, the reserve was gradually lowered to the current 1 XRP.
This reserve remains permanently locked in the account. It cannot be spent. It cannot be used to pay transaction fees. Some XRP Ledger explorers even display the total balance and the locked reserve separately, so wallet owners can clearly see how much XRP is actually available for spending.
The Stellar network follows a similar logic. An address does not exist in the ledger until it receives a minimum balance. A Stellar account requires at least 1 XLM to be activated and remain operational.
You may remember that I once wrote about an error that turned 1,000 USDC into 1 XLM. The situation described in that article was precisely an example of this mechanism at work: a token transaction, even if correctly signed by the sender, cannot be credited to the recipient unless certain prerequisites are met.
A distinctive feature of both the XRP Ledger and Stellar is that an account cannot receive tokens unless it has explicitly opted in to interact with that specific asset. This is a deliberate design decision by the developers, and it has its advantages.
On other networks, whale and celebrity addresses are often flooded with newly created spam tokens, giving the illusion that the address owner purchased them. On XRP Ledger and Stellar, such spam is impossible - because receiving an asset requires prior authorization.
The Lightning Network is a network of payment channels designed to send bitcoin without recording every transfer on the blockchain. Unlike regular on-chain transactions, a Lightning payment is not validated by all nodes in the network and is not confirmed by miners in a block. Instead, it travels through a chain of intermediary nodes.
And this is where an entire class of non-obvious errors appears.
For a payment to travel from Alice to David through intermediate nodes Bob and Carol, each segment of the route must have sufficient liquidity in the required direction.
The network knows the total capacity of each channel, but it does not know how the balance is distributed between the two parties. This can lead to situations like the following:

As a result, the payment from Alice to David fails with a "route not found" error - even though Alice has sufficient funds, David has an active channel capable of receiving the payment, and a route formally exists on the network graph.
There is another particularly tricky nuance. In LND, one of the most widely used Lightning node implementations, the default routing fee limit is set to 0 satoshis.
This means the node will only attempt to find completely free routes - which, in a real network, practically do not exist. Users who never changed this default setting may repeatedly see a "route not found" error, even though the payment would succeed if they allowed a small routing fee.
This is not a flaw. On the contrary, the LND developers deliberately chose not to decide on behalf of users what maximum fee they are willing to pay. If a positive limit had been set by default, users might later discover that routing fees were deducted without them realizing it.
Other reasons for a "route not found" error:
We encounter all of these issues when exchanging bitcoin via the Lightning Network. They may seem unusual compared to traditional blockchain transactions, but each of these problems has a solution. That is why, at Rabbit.io, you can both send and receive bitcoin over the Lightning Network without worrying about these pitfalls.
USDT and USDC are centrally managed stablecoins. Their smart contracts include blacklist functions: the issuers - Tether and Circle - may add an address to a blacklist at any time, after which operations involving the tokens on that address become impossible.
This is a well-known fact. What is less widely understood is that the restriction mechanisms in USDT and USDC are fundamentally different - and that difference has important practical consequences.
In the USDC contract, the blacklist check applies to both the sender and the recipient. If the recipient address is blacklisted, the transaction will be rejected by the smart contract. The sender simply loses a small amount of gas, while the USDC remain in their wallet.
From the sender's perspective, this is a safer model: the funds do not disappear into a frozen address.
In the USDT contract (TetherToken), the transfer function contains the following check: require(!isBlackListed[msg.sender]). This means that only the sender is checked against the blacklist. The recipient address is not validated during the transfer.
In practice, this leads to the following consequences:
Neither the recipient nor anyone else will be able to move those tokens afterward - outgoing transactions from a blacklisted address are prohibited. Only the issuer, Tether, can intervene, using the destroyBlackFunds function to effectively wipe the tokens from the blacklisted address.
In this particular case, one might argue that it is better for a correctly constructed transaction to fail outright. The approach implemented in the USDC contract seems more transparent and fair than the USDT model, where the transaction succeeds - only for it to later become clear that the transfer was effectively pointless.
My recommendations:
That said, even USDT transfers can sometimes fail outright - even when all the transaction data appears to be correct. In Part II of this article, I will cover such cases, along with lesser-known transaction constraints on the Bitcoin, Ethereum, and Tron networks.
It will be published here in exactly one week.