ethers.js: tx.wait() never resolves
I’m facing a strange issue when testing with ganache and increasing my blockTime
to greater than 0 to simulate network congestion and failures.
The following code works just fine (meaning it fails and returns the reason for failure) when ganache’s blockTime is 0:
try {
let tx = await contractWithSigner.contractFunction(someData, { gasLimit: 1 });
await tx.wait();
} catch (e) { console.log(e); }
As soon as I increase ganache’s blockTime
to any arbitrary number: ganache-cli -b 5
, the same code never resolves the tx.wait()
and ethers is stuck in a loop of sending out a call for transactionReceipt
forever.
I can see in ganache’s output that it does indeed send out the failed transaction receipt message in the block immediately following the contract call. Is my assumption on how this should work incorrect?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 8
- Comments: 58 (16 by maintainers)
issue still relevant
@fafrd If this is the only reason tx.wait hangs, this is great news. We can just run a Promise race to account for that, something like
This is a scary way to do it. That should already be what the internal
.wait
is doing, except the.wait
enforces exponential back-off and will use additional hints from the provider to optimize the network usage.If you need an immediate solution, I would recommend using the
provider.waitForTransaction(hash, confirms?, timeout?)
which allows a timeout.I’m looking into this now, and will let you know what I find shortly. 😃
@ricmoo I’m able to recreate this issue! It can occur with low-fee transactions that drop out of the mempool.
I’m using a JsonRpcProvider, testing on rinkeby testnet with infura https:// endpoint.
To recreate:
In a separate repl, after some time we see that the transaction dropped from the mempool altogether:
But the
wait()
is still hanging! Furthermore, if I ctrl-c kill thewait()
, then restart it (against the same TransactionReceipt object) it will still hang.EDIT: After reading more closely, I see ricmoo mentioned that tx.wait() will not resolve if the tx is never mined:
Thus, tx.wait() is not an appropriate function to use if there is concern that the tx will never be mined. I guess it should be used in parallel with some kind of polling mechanism to check that the tx is still present in the mempool at all.
Use
provider.getTransactionReceipt(tx.hash);
to fetch the receipt. Put the whole thing into a loop and poll for the result.Break the loop once the tx receipt is received.
Snippet:
Facing the same issue of
tx.wait()
not resolving or returning an error when a transaction is not picked up by the mining pool on Polygon/Matic.Ideally, for a transaction that is submitted to nodes but isn’t mined in a certain amount of time, we would want
tx.wait()
to return an error of some kind. Right now it appears to just get stuck. @ricmoo any ideas on a temporary fix?Guys, check
pollingInterval
value in your providers. I was having pollingInterval=1200000(I set it for some test purpose and forgot about it) and mywait()
didn’t work. But after changing it to 2000 - it start to work. I didn’t think that it’s common case issue, but anyway it can help in some cases.Facing the same issue of
tx.wait()
not resolving indefinitely. But it only happens infrequently, not always.Does
tx.wait()
accept a timeout, or is it only available forprovider.waitForTransaction()
? Tagging a related issue: #1775Would be nice if
tx.wait()
had the timeout too.Error logs says the following:
What might be causes for the PollingBlockTracker to error out?
Hey all, I figured out the issue and its very noob of me 🙈 the account that I was doing the transaction on had no currency, so it couldn’t pay the gas fees.
I still think this is somewhat of an issue because without a manual timeout catch, you would have no way of picking up this error. So a good suggestion for a PR is to check the accounts balance first and return an error, or to use a timeout. (I am now manually checking balance first which is also actually okay - main point is still that a useful error message is better than an infinite wait)
One of xDai chain users also reported about infinite
tx.wait()
:The error Timeout is returned by Nethermind client when the transaction cannot be handled in time. But
tx.wait()
stalls. Can the reason be in theTimeout
error message? I guess,ethers.js
should handle any errors.Can you give advice on how to set a timeout on
ethers.js
level? For example, inweb3
we havetransactionBlockTimeout
,transactionConfirmationBlocks
, andtransactionPollingTimeout
options.@ricmoo I changed from ankr to morails (i’m on bsc blockchain). I only changed the ws:// link and the code worked fine. Maybe the problem is on ankr api.
@TeaH4nd have you been able to solve this problem? It happens to me too. The transaction went through but
tx.wait()
just never resolves.PS: I’m on mainnet.
I’ve been having the same issue but I believe I have a more realistic gasPrice and the transaction still never goes through. Just hangs indefinitely on
tx.wait()
:Thanks @Benjythebee, I have this issue opened in a tab to investigate once v5.2 is released, so this is good to know. 😃